题目
思路
考虑什么情况下后手可以赢:已经在桌面上的巧克力棒,异或值为 0 0 0 ,而盒子里的巧克力棒,没有异或和为 0 0 0 的子集。此时,先手在桌面上操作,则后手保持异或值为 0 0 0 ,拿走最后一个巧克力棒;先手从盒子里拿出一些巧克力棒,由于异或和不为 0 0 0 ,后手可以保持桌面上的巧克力棒异或值为 0 0 0 ,回到了上一个情况。
如果盒子里的巧克力棒中,有异或值为 0 0 0 的子集,那么先手就拿走它,并且使盒子中剩下的巧克力棒没有异或值为 0 0 0 的子集。做到这一点很简单,如果剩下的巧克力棒有异或值为 0 0 0 的子集,就一并拿走。而此时,这个场景成为了上面的情况。于是先手赢了。
所以唯一的问题就是判定,盒子里的巧克力棒是否有异或值为 0 0 0 的子集。可以使用线性基。
代码
// 湘妹儿,永远滴神!
#include <cstdio>
#include <iostream>
#include <vector>
using namespace std;
typedef long long int_;
int_ readint(){
int_ x; cin >> x; return x;
}
void writeint(int_ x){
cout << x;
}
void endline(){ cout << endl; }
struct XXJ{
int_ d[63], all; int siz;
void init(){
for(int i=0; i<63; ++i)
d[i] = 0;
siz = all = 0;
}
void insert(int_ x){
all |= x; // 就这么简单
for(int i=62; i>=0&&x; --i){
if((x>>i&1) == 0) continue;
if(d[i] == 0)
d[i] = x, ++ siz;
x ^= d[i]; // 嘿嘿嘿
}
}
int size() const { return siz; }
int_ getAll() const { return all; }
} xez;
int main(){
for(int T=10; T; --T){
xez.init(); int n = readint();
for(int i=0; i<n; ++i)
xez.insert(readint());
cout <<(xez.size() == n ?
"YES" : "NO");
endline();
}
return 0;
}