似乎是在美术课上听老师扯淡的时候突然YY出来的?
如果所有的箱子都是打开的,那么就是Nim游戏,直接看Nim和也就是异或和是否为0,是的话先手就输。但是现在有些箱子是打开的,同样也可以尝试用一般Nim游戏的思路来看这道题。
根据终态,很容易可以出猜测出如果打开的箱子的Nim和为0的时候先手必败。但是这是有条件的,必须要把最大的的Nim和为0的子集先打开,否则即使当前Nim和为0,后手仍然可以把剩余的Nim和为0的子集打开,这样就会改变状态。
下面分情况讨论一下。
如果存在Nim和为0的子集,那么先手先把最大的子集打开,此时未开的箱子里不存在Nim和为0的子集。后手如果在开了的箱里取数,就照Nim游戏那样玩。如果后者打开关着的箱,此时开着的箱的Nim和不为0,同样照Nim游戏那样玩。总之不论怎么搞,先手都可以像普通的Nim游戏一样把Nim和取到0。故此时先手必胜。
如果不存在Nim和为0的子集,那么先手不论开哪些箱,后手总可以使Nim和改为0,故此时先手必败。
因此就可以得到先手必胜当且仅当存在子集异或和为0的结论。
数据范围很小,直接暴力状压就能A。
时间复杂度O(Tn2n)。那些0ms的是smg = =
#include <bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define For(i,a,b) for(int i=a;i< b;i++)
#define shl(i) (1 << (i))
inline int rd() {
char c = getchar();
while (!isdigit(c)) c = getchar() ; int x = c - '0';
while (isdigit(c = getchar())) x = x * 10 + c - '0';
return x;
}
int n , a[21];
void input() {
n = rd();
For (i , 0 , n) a[i] = rd();
}
void solve() {
int all = shl(n);
For (s , 1 , all) {
int sg = 0;
For (i , 0 , n) if (shl(i) & s) sg ^= a[i];
if (!sg) {
puts("Yes");
return;
}
}
puts("No");
}
int main() {
#ifndef ONLINE_JUDGE
freopen("data.txt" , "r" , stdin);
#endif
per (T , rd() , 1) {
input();
solve();
}
return 0;
}