HDU

原题链接

题意:

给定一种矩阵生成方式,现在给一个数组 $A$ ,然后询问某个子矩阵的和,$x,y<1e8$;

思路:

矩阵是无限大的,所求的子矩阵范围也较大,于是就表找规律,发现当$L$为奇数时,周期为$L$,反之为$2*L$;

那么我们就可以把周期一致看作$2*L$,然后做一下前缀和,就可以直接求了。此类题目要善于总结!

 1 /*
 2 * @Author: windystreet
 3 * @Date:   2018-08-06 10:27:38
 4 * @Last Modified by:   windystreet
 5 * @Last Modified time: 2018-08-06 20:48:57
 6 */
 7 #include<bits/stdc++.h>
 8 
 9 using namespace std;
10 
11 #define X first
12 #define Y second
13 #define eps  1e-5
14 #define gcd __gcd
15 #define pb push_back
16 #define PI acos(-1.0)
17 #define lowbit(x) (x)&(-x)
18 #define bug printf("!!!!!
");
19 #define mem(x,y) memset(x,y,sizeof(x))
20 
21 typedef long long LL;
22 typedef long double LD;
23 typedef pair<int,int> pii;
24 typedef unsigned long long uLL;
25 
26 const int maxn = 1e5+2;
27 const int INF  = 1<<30;
28 const int mod  = 1e9+7;
29 
30 int s[110][110];
31 int a[100];
32 int sum[110][110];
33 int L;
34 
35 LL cal(int s,int t){                                           // 计算(0,0,)到(s,t)的前缀和
36     int x = s%L,cntx = s/L;
37     int y = t%L,cnty = t/L;
38     return 1ll*sum[x][L-1]*cnty+1ll*sum[L-1][y]*cntx+1ll*sum[L-1][L-1]*cntx*cnty+1ll*sum[x][y];
39 }
40 
41 void solve(){
42     int Q,x1,y1,x2,y2;
43     scanf("%d",&L);
44     for(int i=0;i<L;i++){
45         scanf("%d",&a[i]);
46     }
47     int cur = 0;
48     for(int i=0;i<10*L;++i){                                // 矩阵生成器
49         for(int j=0;j<=i;++j){
50             s[j][i-j] = a[cur];
51             cur = (cur + 1) % L;
52         }
53     }
54     L = 2*L;
55     sum[0][0] = s[0][0];                                    // 计算(2*L)*(2*L)矩阵的前缀和
56     for(int i=1;i<L;i++)sum[0][i] = sum[0][i-1] + s[0][i];
57     for(int i=1;i<L;i++)sum[i][0] = sum[i-1][0] + s[i][0];
58     for(int i=1;i<L;i++){
59         for(int j=1;j<L;j++){
60             sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + s[i][j];
61         }
62     }
63     scanf("%d",&Q);
64     while(Q--){
65         scanf("%d%d%d%d",&x1,&y1,&x2,&y2);                    // 容斥一下
66            printf("%lld
",cal(x2,y2)-cal(x2,y1-1)-cal(x1-1,y2)+cal(x1-1,y1-1));
67     }
68     return;
69 }
70 
71 int main()
72 {
73 //    freopen("in.txt","r",stdin);
74 //    freopen("out.txt","w",stdout);
75 //    ios::sync_with_stdio(false);
76     int t = 1;
77     scanf("%d",&t);
78     while(t--){
79     //    printf("Case %d: ",cas++);
80         solve();
81     }
82     return 0;
83 }
原文地址:https://www.cnblogs.com/windystreet/p/9432919.html