hdu 1850 题解

题目

题意:n堆扑克牌,每次可以取走一堆中任意张数的扑克牌,问先手胜利第一步有几种可能。

这一题如果除去后面一问就直接问先手赢还是后手赢,这就是一道简单的 $ NIM $ 博弈问题。

定理

$ \ \ \ \ \ \ \ \ \ NIM $ 博弈先手必胜,当且仅当 $ A_1 xor A_2 xor A_3....xorA_ixor.....A_n \neq 0 $

具体证明李煜东书上有,这里不做阐述。(可用数学归纳法进行证明

在了解到这个定理后我们还要知道一个式子

$ a \ xor \ b =c \ ,b \ xor \ c =a \ ,a \ xor \ c =b \ , $

首先如果当前场面先手必败,那么答案就是 $ 0 $

如果当前场面先手必胜那么 $ A_1 xor A_2 xor A_3....xorA_ixor.....A_n \neq 0 $ ,我们可以假设存在一个 $ A_j $ 使得 $ A_1 xor A_2 xor A_3....xorA_jxor.....A_n = 0 $ 那么我们可以设 $tmp= A_1 xor A_2 xor A_3....xorA_ixor.....A_n \neq 0 $ 就可以得到 $ tmp \ xor A_i= 0 \ xor A_j $ 即 $ tmp \ xor A_i= A_j $ 那么很显然我们就是要去统计有多少个合法的 $ A_j $那么依据题意我们知道保证 $ A_i > A_j $ 即可。

代码

#include<bits/stdc++.h>
using namespace std;
int n,a[110];
int main(){
	while(scanf("%d",&n)&&n){
		int tmp=0,ans=0;
		for(int i=1;i<=n;++i){
			scanf("%d",&a[i]);
			tmp^=a[i];
		}
		for(int i=1;i<=n;++i){
			if(a[i]>(tmp^a[i])) ans++;
		}
		printf("%d\n",ans);
	}
	return 0;
}
posted @ 2019-11-03 21:20  End_donkey  阅读(197)  评论(0编辑  收藏  举报