Being a Good Boy in Spring Festival HDU - 1850 博弈论,利用异或的性质

  • 由于在一堆中可以取任意张牌,所以对于一个堆的牌数量 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 xy=0 。根据异或的性质,对于一个非0的数 x x x ,有 x ⊕ x = 0 x\oplus x=0 xx=0
  • 所以假设要在第 i i i 堆进行操作,先将 a n s ′ = a n s ⊕ s g [ a i ] ans'=ans\oplus sg[a_i] ans=anssg[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;
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;
}

猜你喜欢

转载自blog.csdn.net/bloom_er/article/details/113775241
今日推荐