LOJ6516 「雅礼集训 2018 Day11」进攻!

Link
对于任意一个矩阵而言,矩阵内\(1\times1\)的小矩形数量加上\(2\times2\)的小矩形数量减去\(1\times2,2\times1\)的小矩形数量恰好等于\(1\)
那么只需要对每个点统计以该点为右下角的矩形中,有多少个包含了上述形状的矩形。
单调栈+差分前缀和求出即可,数据比较水暴力求也可以。

#include<cstdio>
using i64=long long;
const int N=2007,P=998244353,coef[4]={1,-1,-1,1};
char mp[N][N];int sum[N][N];i64 f[4][N][N];
i64 pow(i64 a,i64 b){i64 r=1;for(;b;b>>=1,a=a*a%P)if(b&1)r=r*a%P;return r;}
int main()
{
    int n,m,t;i64 ans=0;scanf("%d%d%d",&n,&m,&t);
    for(int i=1;i<=n;++i) scanf("%s",mp[i]+1);
    for(int i=1;i<=n;++i) for(int j=1;j<=m;++j) sum[i][j]=sum[i][j-1]+(mp[i][j]&15);
    for(int k=0;k<4;++k)
	for(int i=1;i<=n;++i)
	    for(int j=1;j<=m;++j)
		for(int y=j,v;y<=m&&mp[i][y]&15;++y)
		    for(int x=i,u;x<=n&&sum[x][y]-sum[x][j-1]==y-j+1;++x)
			u=x+(k>1),v=y+(k&1),++f[k][i][j],++f[k][u][v],--f[k][i][v],--f[k][u][j];
    for(int k=0;k<4;++k)
	for(int i=1;i<=n;++i)
	    for(int j=1;j<=m;++j)
		f[k][i][j]=(f[k][i][j]+f[k][i-1][j]+f[k][i][j-1]-f[k][i-1][j-1]+P)%P;
    for(int k=0;k<4;++k)
	for(int i=1;i<=n;++i)
	    for(int j=1;j<=m;++j)
		ans=(ans+coef[k]*pow(f[k][i][j],t)+P)%P;
    printf("%lld",ans);
}
posted @ 2020-05-21 14:50  Shiina_Mashiro  阅读(400)  评论(0编辑  收藏  举报