CF 1270I - Xor on Figures

链接

按位考虑的话,相当于是每一位在 \(\bmod 2\) 意义下做循环卷积,该位上有一个 \(G*F=T\) ,其中 \(F,G\) 给定(每一位的 \(F\) 一样)。

我们尝试找这个 \(F\) 在循环卷积意义下的逆。

首先我们不妨设 \([x^0y^0] F= 1\) 可以通过让所有位置循环的移动来实现这件事。

考虑 \(F^2\) ,考虑两个为 \(1\) 的位置 \((x_1,y_1)\)\((x_2,y_2)\) 显然 \((x_2,y_2), (x_1,y_1)\) 也会有贡献,因为是异或这两个抵消掉了。

于是原来的 \((x,y)\) 会在取平方后变成 \((2x,2y)\)

容易发现 \(F^{(2^k)}\) 恰好等于 \(1\)

于是 \(F^{2^k-1}\)\(F\) 的一个逆。

而如果有多个逆,则必定存在一个非 \(0\)\(G\) 使得 \(GF=0\) ,而此时 \(G F^{2^k}= 0\) ,故 \(G = 0\)

于是这个逆是唯一的。故原题解唯一,暴力乘上 \(F^{2^k}\) 即可。

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int k, n, vec;
const int N = 1<<9;
ll a[N][N], b[N][N];
int x[N], y[N];

int main()
{
	cin >> k;n=1<<k;
	for(int i=0;i<n;i++)for(int j=0;j<n;j++)scanf("%lld",&a[i][j]);
	cin >> vec;
	for(int i=0;i<vec;i++){
		scanf("%d%d",&x[i],&y[i]);
	}
	for(int i=vec-1;~i;i--){
		x[i]-=x[0],y[i]-=y[0];
	}
	for(int t=0;t<k;t++){
		for(int i=0;i<n;i++)for(int j=0;j<n;j++)b[i][j]=0;
		for(int i=0;i<n;i++){
			for(int j=0;j<n;j++){
				for(int q=0;q<vec;q++){
					int nxtx=(i+x[q])&(n-1), nxty=(j+y[q])&(n-1);
					b[nxtx][nxty]^=a[i][j];
				}
			}
		}
		for(int i=0;i<n;i++)for(int j=0;j<n;j++)a[i][j]=b[i][j];
		for(int i=0;i<vec;i++)x[i]=(x[i]*2)&(n-1),y[i]=(y[i]*2)&(n-1);
	}
	int ans=0;
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(a[i][j])ans++;
		}
	}
	cout << ans << endl;
}
posted @ 2020-01-13 21:07  jerome_wei  阅读(308)  评论(0编辑  收藏  举报