https://acm.hdu.edu.cn/showproblem.php?pid=6952
题意:
n条横线m条竖线构成(n-1)*(m-1)的网格图,现在要求在图上沿线画若干个不相交圈,圈与圈之间可以共享点但不能共享线。
某些格子上有一个数0或者1,1表示这个格子周围4条线有奇数条属于画的圈,0表示偶数条。
难点在于如何转化画圈问题
画不相交的圈转化为n*m个交点周围4条线有偶数条属于画的圈
把格子的每条短线看作1个变量
结合0和1的要求构建异或方程组
#include<bits/stdc++.h> using namespace std; #define N 21 bitset<N*N*2>b[N*N*2]; int n,m; int idh[N][N],idl[N][N]; char s[N][N]; const int mod=998244353; long long gauss() { int j,row=0; for(int i=0;i<m;++i) { j=row; while(j<n && !b[j][i]) ++j; if(j==n) continue; swap(b[row],b[j]); for(int k=row+1;k<n;++k) if(b[k][i]) b[k]^=b[row]; ++row; } for(int i=row;i<n;++i) if(b[i].test(m)) return 0; int ans=1; for(int i=1;i<=m-row;++i) ans=1ll*ans*2%mod; return ans; } int main() { // freopen("1.txt","w",stdout); int T,a,e; scanf("%d",&T); while(T--) { scanf("%d%d",&a,&e); m=0; for(int i=1;i<=a;++i) for(int j=1;j<e;++j) idh[i][j]=m++; for(int i=1;i<=e;++i) for(int j=1;j<a;++j) idl[i][j]=m++; n=0; for(int i=1;i<=a;++i) for(int j=1;j<=e;++j) { if(j>1) b[n].set(idh[i][j-1]); if(j<e) b[n].set(idh[i][j]); if(i>1) b[n].set(idl[j][i-1]); if(i<a) b[n].set(idl[j][i]); ++n; // printf("%d %d %d %d\n",idh[i][j-1],idh[i][j],idl[j][i-1],idl[j][i]); } for(int i=1;i<a;++i) scanf("%s",s[i]+1); for(int i=1;i<a;++i) for(int j=1;j<e;++j) if(s[i][j]!='.') { b[n].set(idh[i][j]); b[n].set(idh[i+1][j]); b[n].set(idl[j][i]); b[n].set(idl[j+1][i]); // printf("%d %d %d %d\n",idh[i][j],idh[i+1][j],idl[j][i],idl[j+1][i]); if(s[i][j]=='1') b[n].set(m); ++n; } printf("%d\n",gauss()); for(int i=0;i<n;++i) b[i].reset(); } }