Problem E. Matrix from Arrays(杭电2018年多校第四场+思维+打表找循环节)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6336

题目:

题意:给你一个l个元素的数组a,用题目中的程序构造一个新的矩阵,询问q次,问以(x1,y1)为左上角,(x2,y2)为右下角的矩阵内的元素之和(原点在左上角)。

思路:我们通过打表可以发现这个大矩阵都是以左上角2l*2l的小矩阵M循环出现的,所以对于每次查询我们只需统计他要查询的矩阵包含多少个完整的M,对于那些不构成完整的行列和,我们首先用前缀和统计出来,最后加起来即可。我的方法用下图表示,答案就是S1-S2-S3+S4(S4为左上角那个小正方形):

代码实现如下:

  1 #include <set>
  2 #include <map>
  3 #include <queue>
  4 #include <stack>
  5 #include <cmath>
  6 #include <bitset>
  7 #include <cstdio>
  8 #include <string>
  9 #include <vector>
 10 #include <cstdlib>
 11 #include <cstring>
 12 #include <iostream>
 13 #include <algorithm>
 14 using namespace std;
 15
 16 typedef long long ll;
 17 typedef pair<ll, ll> pll;
 18 typedef pair<ll, int> pli;
 19 typedef pair<int, ll> pil;;
 20 typedef pair<int, int> pii;
 21 typedef unsigned long long ull;
 22
 23 #define lson i<<1
 24 #define rson i<<1|1
 25 #define bug printf("*********\n");
 26 #define FIN freopen("D://code//in.txt", "r", stdin);
 27 #define debug(x) cout<<"["<<x<<"]" <<endl;
 28 #define IO ios::sync_with_stdio(false),cin.tie(0);
 29
 30 const double eps = 1e-8;
 31 const int mod = 10007;
 32 const int maxn = 1e6 + 7;
 33 const double pi = acos(-1);
 34 const int inf = 0x3f3f3f3f;
 35 const ll INF = 0x3f3f3f3f3f3f3f;
 36
 37 int t, l, q;
 38 ll sum;
 39 int a[15], mp[105][105];
 40 ll sum1[105], sum2[105];
 41
 42 void init() {
 43     int cnt = 0;
 44     for(int i = 0; i < 4 * l; ++i) {
 45         for(int j = 0; j <= i; ++j) {
 46             mp[j][i-j] = a[cnt];
 47             cnt = (cnt + 1) % l;
 48         }
 49     }
 50     sum = 0;
 51     memset(sum1, 0, sizeof(sum1));
 52     memset(sum2, 0, sizeof(sum2));
 53     for(int i = 0; i < 2 * l; i++) {
 54         for(int j = 0; j < 2 * l; j++) {
 55             sum += mp[i][j];
 56         }
 57     }
 58     for(int i = 0; i < 2 * l; ++i) {
 59         for(int j = 0;  j < 2 * l; ++j) {
 60             sum1[i] += mp[i][j];
 61         }
 62     }
 63     for(int j = 0; j < 2 * l; ++j) {
 64         for(int i = 0;  i < 2 * l; ++i) {
 65             sum2[j] += mp[i][j];
 66         }
 67     }
 68 }
 69
 70 ll query(int x, int y) {
 71     ll rec = 0;
 72     int xx = (x + 1) / (2 * l), yy = (y + 1) / (2 * l);
 73     x = (x + 1) % (2 * l), y = (y + 1) % (2 * l);
 74     rec = sum * xx  * yy;
 75     for(int i = 0; i < y; i++) rec += xx * sum2[i];
 76     for(int i = 0; i < x; i++) rec += yy * sum1[i];
 77     for(int i = 0; i < x; i++) {
 78         for(int j = 0; j < y; j++) {
 79             rec += mp[i][j];
 80         }
 81     }
 82     return rec;
 83 }
 84
 85 int main() {
 86     //FIN;
 87     scanf("%d", &t);
 88     while(t--) {
 89         scanf("%d", &l);
 90         for(int i = 0; i < l; i++) {
 91             scanf("%d", &a[i]);
 92         }
 93         init();
 94         scanf("%d", &q);
 95         int x0, y0, x2, y2;
 96         while(q--) {
 97             scanf("%d%d%d%d", &x0, &y0, &x2, &y2);
 98             printf("%lld\n", query(x2, y2) - query(x0 - 1, y2) - query(x2, y0-1) + query(x0-1, y0-1));
 99         }
100     }
101     return 0;
102 }

原文地址:https://www.cnblogs.com/Dillonh/p/9404289.html

时间: 2024-10-29 16:34:59

Problem E. Matrix from Arrays(杭电2018年多校第四场+思维+打表找循环节)的相关文章

杭电2018多校第四场(2018 Multi-University Training Contest 4) 1005.Problem E. Matrix from Arrays (HDU6336) -子矩阵求和-规律+二维前缀和

6336.Problem E. Matrix from Arrays 不想解释了,直接官方题解: 队友写了博客,我是水的他的代码 ------>HDU 6336 子矩阵求和 至于为什么是4倍的,因为这个矩阵是左上半边有数,所以开4倍才能保证求的矩阵区域里面有数,就是图上的红色阴影部分,蓝色为待求解矩阵. 其他的就是容斥原理用一下,其他的就没什么了. 代码: 1 //1005-6336-矩阵求和-二维前缀和+容斥-预处理O(1)查询输出 2 #include<iostream> 3 #in

2018 HDU多校第三场赛后补题

2018 HDU多校第三场赛后补题 从易到难来写吧,其中题意有些直接摘了Claris的,数据范围是就不标了. 如果需要可以去hdu题库里找.题号是6319 - 6331. L. Visual Cube 题意: 在画布上画一个三维立方体. 题解: 模拟即可. 代码: #include <bits/stdc++.h> using namespace std; int a, b, c, R, C; char g[505][505]; int main () { int T; cin >>

杭电2018多校第一场(2018 Multi-University Training Contest 1) 1001.Maximum Multiple (HDU6298)-数学思维题(脑子是个好东西,可惜我没有)

暑假杭电多校第一场,这一场是贪心场,很多贪心的题目,但是自己太菜,姿势挫死了,把自己都写吐了... 2018 Multi-University Training Contest 1 HDU6298.Maximum Multiple 题目意思就是给你一个n,找出来三个数x,y,z, 使得n=x+y+z,而且x,y,z都是n的因数,并且x*y*z为最大值,让你输出来x*y*z的最大值.如果没有满足条件的情况就输出-1. 由1=1/2+1/3+1/6=1/3+1/3+1/3=1/2+1/4+1/4,所

杭电2018多校第四场(2018 Multi-University Training Contest 4) 1004.Problem D. Nothing is Impossible (HDU6335) -思维题

6335.Problem D. Nothing is Impossible 题意:给你n道题目,m个人,每题有x个正确选项,y个错误选项,问你做对题数量最多的人做对了多少道题目. 如果一道题有y个错误选项,那么我需要至少y+1个人才能保证一定有一个人做对了这道题目,所以题面上给的正确选项的数量x并没有什么实质性的作用... 假设第一题错误选项有y1个,第二题错误选项有y2个,那么怎么才能保证至少有一个人两道题目都做对了呢? 首先我需要至少y1+1个人才能保证一定有一个人做对了第一题,那么,我在做

杭电2018

斐波那契数列问题,公式:  f(n)= f(n-1)+f(n-3) 代码: #include "stdio.h" long long dp[55]; int main(){ int i,n; dp[1]=1; dp[2]=2; dp[3]=3; dp[4]=4; for(i=5;i<=55;i++){ dp[i]=dp[i-1]+dp[i-3]; } while(~scanf("%d",&n) && n!=0){ printf(&quo

杭电2018母牛的故事

program description 有一头母牛,它每年年初生一头小母牛.每头小母牛从第四个年头开始,每年年初也生一头小母牛.请编程实现在第n年的时候,共有多少头母牛? input 输入数据由多个测试实例组成,每个测试实例占一行,包括一个整数n(0<n<55),n的含义如题目中描述.n=0表示输入数据的结束,不做处理. output 对于每个测试实例,输出在第n年的时候母牛的数量.每个输出占一行. sample input 2 4 5 0 sample output 2 4 6 不多说,代码

杭电2018多校第一场(2018 Multi-University Training Contest 1) 1008.RMQ Similar Sequence (HDU6305) -笛卡尔树+数学期望

6305.RMQ Similar Sequence 这个题的意思就是对于A,B两个序列,任意的l,r,如果RMQ(A,l,r)=RMQ(B,l,r),B序列里的数为[0,1]的实数,B的重量为B的所有元素的和,否则为0.问你B的期望重量是多少. dls讲题说是笛卡尔树,笛卡尔树是一种特定的二叉树数据结构,具体的看这篇博客吧:[pushing my way]笛卡尔树 这个题就是笛卡尔树同构的问题,假设A的笛卡尔树的子树大小为sz[u],那么序列B与A同构的概率为,因为B中的数满足均匀分布(因为B中

2019杭电多校第四场hdu6621 K-th Closest Distance(二分答案+主席树)

K-th Closest Distance 题目传送门 解题思路 二分答案+主席树 先建主席树,然后二分答案mid,在l和r的区间内查询[p-mid, p+mid]的范围内的数的个数,如果大于k则说明这个范围内存在第k小的数,r=mid,否则不存在,l=mid+1. 代码如下 #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; inline int read(){

2019 杭电多校 第四场

2019 Multi-University Training Contest 4 补题链接:2019 Multi-University Training Contest 4 1001 AND Minimum Spanning Tree (HDU 6614) 题意 给定一个有 \(N\) 个结点的完全图,编号从 \(1\) 到 \(N\).结点 \(x\) 与结点 \(y\) \((1\leq x, y\leq N, x \neq y)\) 的边的权值为 \(x\) 与 \(y\) 按位与的值,求