bzoj 3603
考虑转化问题:一个点相邻元素中有偶数个$1$等价于一个点与相邻元素异或和为$0$
于是直接列出异或方程组求解即可
注意由于要求不允许出现全0矩阵,因此如果有自由元直接给成$1$
贴代码:
#include <cstdio> #include <cmath> #include <cstring> #include <cstdlib> #include <iostream> #include <algorithm> #include <queue> #include <stack> #include <bitset> using namespace std; bitset <1605> a[1605]; int n,m,N; int ret[1605]; int to[5][2]={{0,0},{1,0},{0,1},{-1,0},{0,-1}}; int idx(int x,int y) { return (x-1)*m+y; } bool check(int x,int y) { return x>0&&x<=n&&y>0&&y<=m; } void Gauss() { for(int i=1;i<=N;i++) { int temp=i; while(!a[temp][i]&&temp<=N)temp++; if(temp==N+1) { for(int j=i+1;j<=N;j++)a[i][j]=0; a[i][N+1]=1; continue; } swap(a[i],a[temp]); for(int j=i+1;j<=N;j++)if(a[j][i])a[j]^=a[i]; } for(int i=N;i>=1;i--) { ret[i]=a[i][N+1]; for(int j=i+1;j<=N;j++)if(a[i][j])ret[i]^=ret[j]; } } int main() { scanf("%d%d",&n,&m),N=n*m; for(int i=1;i<=n;i++) { for(int j=1;j<=m;j++) { for(int k=0;k<5;k++) { int toi=i+to[k][0],toj=j+to[k][1]; if(check(toi,toj))a[idx(i,j)][idx(toi,toj)]=1; } } } Gauss(); for(int i=1;i<=n;i++,printf("\n"))for(int j=1;j<=m;j++)printf("%d ",ret[idx(i,j)]); return 0; }