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;
}

猜你喜欢

转载自www.cnblogs.com/weiyanpeng/p/12189324.html
今日推荐