linkkkkk
题意:
Nim游戏,去掉任意堆石子后能否使得先手必输。
思路:
求一个子集,每个式子的状态有取或不取两种,分别设为1 / 0。
列一个方程看异或值为0,是否有解。
求异或线性方程组的自由元个数或解的个数。
由于全0是一组解,所以看是否有多组解,即自由元个数是否大于0
代码:
ll n,m=42; ll a[110][110],g[110]; int Gauss(int n,int m)//返回自由元个数 { int r, c; for(r = 0, c = 0; c < n; c++) { int t = -1; for(int i = r; i < m; i++) { if(a[i][c]) { t = i; break; } } if(t==-1) continue; for(int i = c; i < n; i++)///交换 { swap(a[t][i], a[r][i]); } for(int i = r + 1; i < m; i++) { if(a[i][c]) for(int j = c; j <n; j++) { a[i][j] = a[i][j] ^ a[r][j]; } } r++; } return n-r; /*if(r < n) { for(int i = r; i < n; i++) { if(a[i][n]) return 2; } return 1; } for(int i = n - 1; i >= 0; i--) { for(int j = i + 1; j < n; j++) { if(a[i][j]) a[i][n] ^= a[j][n]; } } return 0;*/ } void solve() { cin >> n; for(int i=0;i<n;i++) cin>>g[i]; for(int i=0;i<m;i++) for(int j=0;j<n;j++) a[i][j]=(g[j]>>i)&1; int ans=Gauss(n,m); if(ans>0) puts("Yes"); else puts("No"); } int main() { int _;cin>>_; while(_--) solve(); return 0; }