bzoj4171: Rhl的游戏
头都没了啊啊啊啊啊%%%%
我做过这个的弟弟题,强行枚举第一行按不按就完了
这个不是很会啊,容易想到高斯消元解异或方程组,然而是O(n^3m^3)不支持
结果正解是把这两个做法结合起来
设第一行为未知数,可以把下面所有的未知数用第一行表示出来
具体的,第一行的方程移项表示第二行的未知数,由此类推,最后第n行的方程用来判YES和NO
假如不能按相当于xi,j=0,加方程就好了
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> #include<bitset> using namespace std; const int maxn=256+10; const int maxm=256+10; const int maxK=256+10; bitset<300>s[maxn][maxm];//第i行(滚动)第j列的数被第一排的变量表示,最后一位是常数 bitset<300>q[maxm*10];int u;//高斯消元的方程和数量 void gauss(int m) { int b=1; for(int j=1;j<=m;j++) { for(int i=b;i<=u;i++) if(q[i][j]==1){swap(q[b],q[i]);break;} if(q[b][j]==0)continue; for(int i=1;i<=u;i++) { if(i==b)continue; if(q[i][j])q[i]=(q[i]^q[b]); } b++; } for(int i=b;i<=u;i++) { q[i][m+1]=(q[i][m+1]^1); if(q[i].none()){puts("NO");return ;} } puts("YES"); } char ss[maxm];int mp[maxn][maxm]; int main() { freopen("a.in","r",stdin); freopen("a.out","w",stdout); int T; scanf("%d",&T); for(int T__ORZ__T=1;T__ORZ__T<=T;T__ORZ__T++) { printf("Case #%d:\n",T__ORZ__T); int n,m,K; scanf("%d%d%d",&n,&m,&K); for(int i=1;i<=n;i++) { scanf("%s",ss+1); for(int j=1;j<=m;j++) mp[i][j]=(ss[j]=='W')?0:1; } //.......sc...... u=0; memset(s,0,sizeof(s)); for(int j=1;j<=m;j++)s[1][j][j]=1; for(int i=2;i<=n;i++) for(int j=1;j<=m;j++) { s[i][j]=s[i-1][j-1]^s[i-1][j]^s[i-1][j+1]^s[i-2][j]; s[i][j][m+1]=s[i][j][m+1]^mp[i-1][j]; } int x,y; for(int i=1;i<=K;i++) scanf("%d%d",&x,&y),q[++u]=s[x][y]; for(int j=1;j<=m;j++) { q[++u]=s[n][j-1]^s[n][j]^s[n][j+1]^s[n-1][j]; q[u][m+1]=q[u][m+1]^mp[n][j]; } //....insq...... gauss(m); } return 0; }
pain and happy in the cruel world.