CF1270I Xor on Figures 题解
题目描述
给定一个 \(2^k\times 2^k\) 的矩阵 \(A\) ,下标从零开始。
给定长为 \(t\) 的数组 \(x_i,y_i\) 。
每次操作你可以任选 \(p,q,w\) ,然后对 \(\forall 1\le i\le t\) ,将 \(A[(x_i+p)\bmod 2^k][(y_i+q)\bmod 2^k]\) 异或上 \(w\) 。
求使得 \(A\) 变成全零矩阵的最小操作次数。
数据范围
- \(1\le k\le 9,0\le a_{i,j}\lt 2^{60}\) 。
- \(1\le t\le\min(99,4^k)\) ,保证 \(t\) 为奇数。
- \(1\le x_i,y_i\le 2^k\) 。
时间限制 \(\texttt{5s}\) ,空间限制 \(\texttt{256MB}\) 。
分析
思维难度极高,看完题解感觉好简单。
定义二维数组的异或卷积:
其中两维下标都是在 \(\bmod 2^k\) 意义下。
显然一组 \((p,q)\) 只会被操作至多一次。
记二维数组 \(F\) 满足 \(F[x_i][y_i]=1\) ,操作矩阵 \(G\) 满足 \(G[p][q]=w\) 。
根据题目条件有 \(F\times G=A\) ,目标 \(G\) 的非零元个数最小。
\(\texttt{Key observation}\) : \(F^{2^k}=I\) ,其中 \(I[x][y]=[x=0\wedge y=0]\) 。
证明也很简单:
\(F\) 的高次幂值域为 \(\{0,1\}\) 。
考虑 \(F^2\) ,如果 \(i\neq j\) ,那么 \((i,j),(j,i)\) 都会贡献到 \(F[x_i+x_j][y_i+y_j]\) ,根据异或的性质等于没有贡献。
所以仅有 \(i=j\) 时 \((i,j)\) 才会产生贡献,因此 \(F^2\) 中非零元横纵下标均为偶数。
依此类推, \(F^{2^k}\) 中仅有横纵坐标均为 \(2^k\) 倍数的元素(即 \(F[0][0]\) )可能非零。
再观察 \(1\) 的个数的奇偶性,由于 \(F\) 中有奇数个 \(1\) (因为 \(t\) 为奇数),所以 \(F^{2^k}\) 中也有奇数个 \(1\) ,即 \(F[0][0]=1\) 。
因此 \(F\) 逆元存在,并且 \(F^{-1}=F^{2^k-1}\) 。
因此 \(G\) 唯一确定,并且 \(G=A\times F^{2^k-1}\) 。
由于 \(F\) 中至多只有 \(t\) 个 \(1\) ,所以单次卷积可以做到 \(\mathcal O(t4^k)\) 。
时间复杂度 \(\mathcal O(kt4^k)\) 。
#include<bits/stdc++.h>
#define vvi vector<vector<long long>>
using namespace std;
const int maxn=1e5+5;
int k,n,t,x,y,res;
vvi a,f;
vvi operator*(const vvi &a,const vvi &b)
{
static vvi res(n);
for(int i=0;i<n;i++) res[i].clear(),res[i].resize(n);
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
{
if(!b[i][j]) continue;
for(int p=0;p<n;p++)
for(int q=0;q<n;q++)
res[(i+p)%n][(j+q)%n]^=a[p][q];
}
return res;
}
int main()
{
scanf("%d",&k),n=1<<k,a.resize(n),f.resize(n);
for(int i=0;i<n;i++)
{
a[i].resize(n),f[i].resize(n);
for(int j=0;j<n;j++) scanf("%lld",&a[i][j]);
}
scanf("%d",&t);
while(t--) scanf("%d%d",&x,&y),f[x-1][y-1]=1;
for(int i=0;i<k;i++) a=a*f,f=f*f;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
res+=a[i][j]!=0;
printf("%d\n",res);
return 0;
}
本文来自博客园,作者:peiwenjun,转载请注明原文链接:https://www.cnblogs.com/peiwenjun/p/16600221.html