入阵曲(桶,观察性质)

这一套题的背景.......

60分暴力很简单,不说了。。。。

100分:

我们发现对于一个矩形,我们可以看作两个大矩形相减的形式

那么我们枚举矩形上下边界,然后在定义一个桶

每次将当前矩形%q后塞进桶,同时查找tong[余数]的个数,显然这可以化为小矩形

注意tong[0]=1,然后清空即可

考试怎么没想到

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<map>
 6 #include<vector>
 7 #include<set>
 8 #include<cmath>
 9 #define MAXN 601
10 #define int long long
11 using namespace std;
12 int n,m,q;
13 int read()
14 {
15     int x=0;char c=getchar();
16     while(c<'0'||c>'9')c=getchar();
17     while(c>='0'&&c<='9')
18     {
19         x=(x<<1)+(x<<3)+(c^48);
20         c=getchar();
21     }
22     return x;
23 }
24 int tong[1000001];int cha[MAXN];
25 int sum[MAXN][MAXN],a[MAXN][MAXN];int ans=0;
26 int getsum(int x1,int y1,int x2,int y2)
27 {
28      return sum[x1][y1]+sum[x2-1][y2-1]-sum[x1][y2-1]-sum[x2-1][y1];
29 }
30 void work(int l,int r)
31 {
32     tong[0]=1;
33     cha[0]=0;
34     cha[++cha[0]]=0;
35     for(int i=1;i<=m;++i)
36     {
37         int me=getsum(r,i,l,1)%q;
38         ans+=tong[me];
39         tong[me]++;
40         cha[++cha[0]]=me;
41     }
42     for(int i=1;i<=cha[0];++i)tong[cha[i]]=0;
43 }
44 signed main()
45 {
46     n=read();m=read();q=read();
47     for(int i=1;i<=n;++i)
48     {
49         for(int j=1;j<=m;++j)
50         {
51             a[i][j]=read();
52             sum[i][j]=a[i][j]+sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
53         }             
54     }
55     for(int l=1;l<=n;++l)
56     {
57         for(int r=l;r<=n;++r)
58         {
59             work(l,r);
60         }
61     }
62     printf("%lld\n",ans);
63 }
View Code

猜你喜欢

转载自www.cnblogs.com/Wwb123/p/11336145.html