LGP5447题解

考虑一个更强的限制,直接给出一个 \(a\times b\) 的矩形,询问一个 \(n\times m\) 的大矩形有多少个这样的子矩阵。

把矩阵压成字符串,然后跑 KMP,然后在合法的位置上看看这个位置是否能够匹配得上。

路径是一样的,只不过增加了通配符。

通配符什么的用 NTT 代替 KMP 就行了。

不懂为什么是黑的。

#include<cstdio>
#define IMP(lim,act) for(int qwq=(lim),i=0;i^qwq;++i)act
const int N=1505,B=1<<23,mod=5<<25|1;
int n1,m1,n2,m2,k,tm[N][N];int S[B],T[B];
int buf[B<<2],*w[30];char mp[N][N],s[5000005];
inline int id(const int&x,const int&y){
	return(x-1)*m1+y;
}
inline int Getlen(const int&n){
	int len(0);while((1<<len)<n)++len;return len;
}
inline int Add(const int&a,const int&b){
	return a+b>=mod?a+b-mod:a+b;
}
inline int Del(const int&a,const int&b){
	return b>a?a-b+mod:a-b;
}
inline int pow(int a,int b=mod-2){
	int ans(1);for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;return ans;
}
inline void swap(int&a,int&b){
	int c=a;a=b;b=c;
}
inline void init(const int&n){
	const int&m=Getlen(n);int*now=buf;w[m]=now;now+=1<<m;
	w[m][0]=1;w[m][1]=pow(3,mod-1>>m+1);for(int i=2;i^1<<m;++i)w[m][i]=1ll*w[m][i-1]*w[m][1]%mod;
	for(int k=m-1;k>=0&&(w[k]=now,now+=1<<k);--k)IMP(1<<k,w[k][i]=w[k+1][i<<1]);
}
inline void DFT(int*f,const int&M){
	const int&n=1<<M;
	for(int len=n>>1,d=M-1;d>=0;--d,len>>=1){
		for(int k=0;k^n;k+=len<<1){
			int*W=w[d],*L=f+(k),*R=f+(k|len),x,y;IMP(len,(x=*L,y=*R)),*L++=Add(x,y),*R++=1ll**W++*Del(x,y)%mod;
		}
	}
}
inline void IDFT(int*f,const int&M){
	const int&n=1<<M;
	for(int len=1,d=0;d<M;++d,len<<=1){
		for(int k=0;k^n;k+=len<<1){
			int*W=w[d],*L=f+(k),*R=f+(k|len),x,y;IMP(len,(x=*L,y=1ll**W++**R%mod)),*L++=Add(x,y),*R++=Del(x,y);
		}
	}
	const int&k=pow(n);IMP(n,f[i]=1ll*f[i]*k%mod);for(int i=1;(i<<1)<n;++i)swap(f[i],f[n-i]);
}
signed main(){
	scanf("%d%d%d",&n1,&m1,&k);for(int i=1;i<=n1;++i)scanf("%s",mp[i]+1);scanf("%s",s+1);
	int x(0),y(0),_0x(0),_0y(0),_1x(0),_1y(0),ans(0);
	for(int i=1;i<=k;++i){
		if(s[i]=='w')--x;if(s[i]=='a')--y;if(s[i]=='s')++x;if(s[i]=='d')++y;
		if(x<_0x)_0x=x;if(y<_0y)_0y=y;if(x>_1x)_1x=x;if(y>_1y)_1y=y;
	}
	n2=_1x-_0x+1;m2=_1y-_0y+1;tm[x=1-_0x][y=1-_0y]=1;
	for(int i=1;i<=k;++i){
		if(s[i]=='w')--x;if(s[i]=='a')--y;if(s[i]=='s')++x;if(s[i]=='d')++y;tm[x][y]=1;
	}
	int n=n1*m1,m=n2*m1;init(n+m+1);
	for(int i=1;i<=n1;++i)for(int j=1;j<=m1;++j)S[id(i,j)-1]=mp[i][j]-'0';
	for(int i=1;i<=n2;++i)for(int j=1;j<=m2;++j)T[m-id(i,j)+1]=tm[i][j];
	const int&len=Getlen(n+m+1);DFT(S,len);DFT(T,len);IMP(1<<len,S[i]=1ll*S[i]*T[i]%mod);IDFT(S,len);
	for(int i=1;i<=n1-n2+1;++i)for(int j=1;j<=m1-m2+1;++j)if(!S[m+id(i,j)-1])++ans;printf("%d",ans);
}
posted @ 2022-06-23 19:29  Prean  阅读(16)  评论(0编辑  收藏  举报
var canShowAdsense=function(){return !!0};