由于在一堆中可以取任意张牌,所以对于一个堆的牌数量 x x x,有 s g [ x ] = x sg[x]=x sg[x]=x
先求出总的游戏 S G SG SG 值 a n s = s g [ a 1 ] ⊕ s g [ a 2 ] ⊕ . . . ⊕ s g [ a n ] ans=sg[a_1]\oplus sg[a_2] \oplus...\oplus sg[a_n] ans=sg[a1]⊕sg[a2]⊕...⊕sg[an]
若 a n s = 0 ans=0 ans=0 则先手必败。
反之,先手必胜。那么对应第一局的可走的路:假设有两堆牌 x , y x,y x,y,假设取 y y y 中的牌,取完后为 y ′ y' y′ ,则必须满足到后手时为 P P P 点,即满足 x ⊕ y ′ = 0 x\oplus y'=0 x⊕y′=0 。根据异或的性质,对于一个非0的数 x x x ,有 x ⊕ x = 0 x\oplus x=0 x⊕x=0。
所以假设要在第 i i i 堆进行操作,先将 a n s ′ = a n s ⊕ s g [ a i ] ans'=ans\oplus sg[a_i] ans′=ans⊕sg[ai] 得出的是除了第 i i i 堆外剩下的其他堆的总 S G SG SG 值,若该 a n s ′ ans' ans′ ≤ a i a_i ai 则说明可以从该牌堆中取出 a n s ′ ans' ans′ 张牌,使得该游戏的新 S G SG SG 值为0,即对应到后手状态时为 P P P 点。
#include<bits/stdc++.h>
using namespace std;typedeflonglong ll;constint N=1e2+10;int a[N];intmain(){
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);}}return0;}