- 由于在一堆中可以取任意张牌,所以对于一个堆的牌数量 xxx,有 sg[x]=xsg[x]=xsg[x]=x
- 先求出总的游戏 SGSGSG 值 ans=sg[a1]⊕sg[a2]⊕...⊕sg[an]ans=sg[a_1]\oplus sg[a_2] \oplus...\oplus sg[a_n]ans=sg[a1]⊕sg[a2]⊕...⊕sg[an]
- 若 ans=0ans=0ans=0 则先手必败。
- 反之,先手必胜。那么对应第一局的可走的路:假设有两堆牌 x,yx,yx,y,假设取 yyy 中的牌,取完后为 y′y'y′ ,则必须满足到后手时为 PPP 点,即满足 x⊕y′=0x\oplus y'=0x⊕y′=0 。根据异或的性质,对于一个非0的数 xxx ,有 x⊕x=0x\oplus x=0x⊕x=0。
- 所以假设要在第 iii 堆进行操作,先将 ans′=ans⊕sg[ai]ans'=ans\oplus sg[a_i]ans′=ans⊕sg[ai] 得出的是除了第 iii 堆外剩下的其他堆的总 SGSGSG 值,若该 ans′ans'ans′ ≤ aia_iai 则说明可以从该牌堆中取出 ans′ans'ans′ 张牌,使得该游戏的新 SGSGSG 值为0,即对应到后手状态时为 PPP 点。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e2+10;
int a[N];
int main(){
int m;
while(scanf("%d",&m),m){
int ans=0;
for(int i=1;i<=m;++i){
scanf("%d",&a[i]);
ans^=a[i];
}
if(!ans) puts("0");
else{
int cnt=0;
for(int i=1;i<=m;++i){
if((ans^a[i])<=a[i]) ++cnt;
}
printf("%d\n",cnt);
}
}
return 0;
}