入阵曲(桶,观察性质)
这一套题的背景.......
60分暴力很简单,不说了。。。。
100分:
我们发现对于一个矩形,我们可以看作两个大矩形相减的形式
那么我们枚举矩形上下边界,然后在定义一个桶
每次将当前矩形%q后塞进桶,同时查找tong[余数]的个数,显然这可以化为小矩形
注意tong[0]=1,然后清空即可
考试怎么没想到
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }