4.28 省选模拟赛模拟赛 最佳农场 二维卷积 NTT

avatar
avatar

第一次遇到二维卷积 不太清楚是怎么做的。

40分暴力比对即可。

对于行为或者列为1时 容易想到NTT做快速匹配.然后找答案即可。

考虑这是一个二维的比对过程。

\(f_{i,j}\)表示以i,j为右下角的答案。

那么我们把询问矩阵给上下翻转 左右翻转。设初始矩阵为a 询问矩阵为b 且询问矩阵大小为x,y.

那么显然有 \(f_{i,j}=\sum_{l=1}^x\sum_{r=1}^y[b_{l,r}==a_{i-l+1,j-r+1}]\)

这是一个二维卷积的形式 还是考虑转换成一维卷积的形式。

一种构造方法 将询问矩阵扩展成原来矩阵大小的矩阵 那么空位补0.

然后把矩阵按照 i*m+j的编号放下来 做卷积即是\(f_{i,j}\)的答案。

容易发现是正确。

const int MAXN=510,N=600000,G=3;
int g[N],f[N],rev[N],g1[N],f1[N],w[N];
char a[MAXN][MAXN];
int n,m,lim=1,Q;
inline int ksm(int b,int p)
{
	int cnt=1;
	while(p)
	{
		if(p&1)cnt=(ll)cnt*b%mod;
		b=(ll)b*b%mod;p=p>>1;
	}
	return cnt;
}
inline void NTT(int *a,int op)
{
	rep(1,lim-1,i)if(i<rev[i])swap(a[i],a[rev[i]]);
	for(int len=2;len<=lim;len=len<<1)
	{
		int mid=len>>1;
		int wn=ksm(G,op==1?(mod-1)/len:mod-1-(mod-1)/len);
		for(int j=0;j<lim;j+=len)
		{
			int d=1;
			for(int i=0;i<mid;++i)
			{
				int x=a[i+j],y=(ll)a[i+j+mid]*d%mod;
				a[i+j]=(x+y)%mod;a[i+j+mid]=(x-y+mod)%mod;
				d=(ll)d*wn%mod;
			}
		}
	}
	if(op==-1)
	{
		int INV=ksm(lim,mod-2);
		rep(0,lim-1,i)a[i]=(ll)a[i]*INV%mod;
	}
}
inline void prepare(int *g,int *f)
{
	rep(1,n,i)rep(0,m-1,j)
	g[(i-1)*m+j]=(a[i][j]=='G'),f[(i-1)*m+j]=(a[i][j]=='L');
	NTT(g,1);NTT(f,1);
}
inline void calc()
{
	rep(0,lim-1,i)w[i]=((ll)g[i]*g1[i]+(ll)f[i]*f1[i])%mod;
	NTT(w,-1);
}
int main()
{
	freopen("best.in","r",stdin);
	freopen("best.out","w",stdout);
	gt(n);gt(m);
	rep(1,n,i)gc(a[i]);
	int ww=n*(m-1);
	while(lim<ww+ww)lim=lim<<1;
	rep(0,lim-1,i)rev[i]=rev[i>>1]>>1|((i&1)?lim>>1:0);
	prepare(g,f);gt(Q);
	rep(1,Q,cc)
	{
		int x,y;
		gt(x);gt(y);
		memset(a,0,sizeof(a));
		memset(f1,0,sizeof(f1));
		memset(g1,0,sizeof(g1));
		rep(1,x,j)gc(a[j]),reverse(a[j],a[j]+y);
		//rep(1,x,j)printf("%s\n",a[j]);
		rep(1,x/2,j)rep(0,y-1,k)swap(a[j][k],a[x-j+1][k]);
		//rep(1,x,j)printf("%s\n",a[j]);
		prepare(g1,f1);
		calc();
		//rep(0,ww,j)put(w[j]);
		int ans=0,ansl=1,ansr=1;
		rep(x,n,i)
		{
			rep(y-1,m-1,j)
			{
				if(ans<w[(i-1)*m+j])
				{
					ans=w[(i-1)*m+j];
					ansl=i-x+1;ansr=j+1-y+1;
				}
			}
		}
		printf("%d %d\n",ansl,ansr);
	}
	return 0;
}

猜你喜欢

转载自www.cnblogs.com/chdy/p/12805233.html
NTT