2022-6-19 #1 CF1270I & CF1637H
每天都要能选出至少两道有意义的题,这样才算没有摆。
本地记录的话容易鸽掉,就放博客上了。(我博客是不是没啥人看啊)
完了,下午晚上打 CF/AT 去了,今天摆了呜呜。
md,等一下再更。
001 CF1270I Xor on Figures
我们定义两个矩阵 \(A,B\) 的异或卷积 \(C\) 为:
\[C_{a,b}=\oplus_{(u+i)\bmod 2^k=a}\oplus_{(v+j)\bmod 2^k=b}A_{u,v}B_{i,j}
\]
我们发现将所有操作放到一个矩阵 \(P\) 上,再令关键位置形成的矩阵为 \(Q\),那么我们需要 \(P\times Q=A\)。
可以证明,在异或卷积下,矩阵 \(A\) 存在逆元,其值为 \(A^{2^k-1}\)。
那么我们就是要求 \(A\times P^{2^k-1}\),但矩阵快速幂的时候暴力实现异或卷积肯定过不了。
发现 \(P^2\) 只有 \((2x_i\bmod 2^k,2y_i\bmod 2^k)\) 有值,因为 \(((x _i+x_j)\bmod 2^k,(y_i+y_j)\bmod 2^k)\) 会被 \((x_i,y_i),(x_j,y_j)\) 计算一次,\((x_j,y_j),(x_i,y_i)\) 计算一次,抵消了。
于是 \(P^{2^l}\) 也只有 \(O(t)\) 个位置有值,我们异或卷积的时候取这些位置出来计算即可,复杂度 \(O(4^kkt)\)。
#include<stdio.h>
const int maxn=1<<9;
int n,k,ans,m;
struct matrix{
unsigned long long a[maxn][maxn];
inline unsigned long long* operator [](const int &x){
return a[x];
}
matrix operator *(matrix p){
matrix res;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
res[i][j]=0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(p[i][j])
for(int u=0;u<n;u++)
for(int v=0;v<n;v++)
res[(u+i)%n][(v+j)%n]^=p[i][j]*a[u][v];
return res;
}
}A,B;
int main(){
scanf("%d",&k),n=1<<k;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
scanf("%llu",&A[i][j]);
scanf("%d",&m);
for(int i=1,x,y;i<=m;i++)
scanf("%d%d",&x,&y),B[x-1][y-1]=1;
for(int i=0;i<k;i++)
A=A*B,B=B*B;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
ans+=(A[i][j]!=0);
printf("%d\n",ans);
return 0;
}