【题解】洛谷 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;
}
posted @ 2020-10-17 14:17  破壁人五号  阅读(78)  评论(0编辑  收藏  举报