【题解】洛谷 P3941 入阵曲【20201017 CSP 模拟赛】
题意
给定 \(n\times m\) 的矩阵,问有多少个子矩阵的和是 \(k\) 的倍数。\(n,m\leq 400\)。
题解
预处理每一行的前缀和。枚举矩形左右是哪两列,用桶记录前 \(i\) 行的前缀和模 \(k\) 的值。时间复杂度 \(O(nm^2)\)。
注意减了之后取模可能有负数。
#include<bits/stdc++.h>
using namespace std;
const int LEN=1e6;
char buf[LEN+10],*PT=buf+LEN;
inline char gc(){
	return (PT==buf+LEN)?(fread(buf,1,LEN,stdin),PT=buf,*(PT++)):*(PT++);
}
inline int getint(){
	int ans=0;
	char c=gc();
	while(c<'0'||c>'9')c=gc();
	while(c>='0'&&c<='9'){
		ans=ans*10+c-'0';
		c=gc();
	}
	return ans;
}
const int N=410;
int n,m,k,a[N][N];
int b[N][N],c[1000100];
int _(int x){ return x>=k?x-k:x; }
int main(){
	n=getint(),m=getint(),k=getint();
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			a[i][j]=getint();
			b[i][j]=_(b[i][j-1]+a[i][j]);
		}
	}
	long long ans=0;
	for(int i=0;i<m;i++){
		for(int j=i+1;j<=m;j++){
			c[0]++;
			int s=0;
			for(int l=1;l<=n;l++){
				int t=_(b[l][j]-b[l][i]+k);
				s=_(s+t);
				ans+=c[s];
				c[s]++;
			}
			s=0;
			for(int l=1;l<=n;l++){
				int t=_(b[l][j]-b[l][i]+k);
				s=_(s+t);
				c[s]=0;
			}
			c[0]=0;
		}
	}
	cout<<ans;
}


                
            
        
浙公网安备 33010602011771号