踩踩时间复杂度不正确的高斯消元
首先可以发现第一行确定后就可以确定整个矩阵,所以可以枚举第一行的所有状态然后$O(n)$递推检查是否合法
$O(n)$递推的方法是这样的:设$pre$为上一行,$now$为当前行,$nxt$为递推出的下一行,$all$为列的全集,则可以直接用位运算完成递推:
$nxt=all&((now<<1)xor(now>>1)xor$ $now$ $xor$ $pre)$
递推后第$n+1$行为空则说明可行
问题来了,第一行的状态有$O(2^{40})$种,会$T$。但是有一个鬼畜的性质是如果存在合法解一定有一个对称的合法解,然后就可以$O(n*2^{frac{n}{2}})$出解了=。=
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=50; 6 int mapp[N][N]; 7 long long n,m,mid,all,half; 8 long long fir,las,noww,tmp; 9 int check(int a,int b) 10 { 11 return mapp[a][b]^mapp[a-1][b]^mapp[a][b-1]^mapp[a][b+1]; 12 } 13 int main () 14 { 15 scanf("%lld%lld",&n,&m); 16 mid=(m+1)/2,all=(1ll<<m)-1,half=(1ll<<mid)-1; 17 for(int i=1;i<=half;i++) 18 { 19 fir=0; 20 for(int j=1;j<=mid;j++) 21 if(i&(1ll<<(j-1))) fir|=(1ll<<(j-1))|(1ll<<(m-j)); 22 las=noww=all&(fir^(fir<<1)^(fir>>1)),tmp=fir; 23 for(int j=2;j<=n;j++) 24 las=noww,noww=all&(noww^(noww<<1)^(noww>>1)^tmp),tmp=las; 25 if(!noww) break; 26 } 27 for(int i=1;i<=m;i++) 28 mapp[1][i]=(fir&(1ll<<(i-1)))?1:0; 29 for(int i=2;i<=n;i++) 30 for(int j=1;j<=m;j++) 31 mapp[i][j]=check(i-1,j); 32 for(int i=1;i<=n;i++) 33 { 34 for(int j=1;j<=m;j++) 35 printf("%d ",mapp[i][j]); 36 printf(" "); 37 } 38 return 0; 39 }