[Nim游戏]

[模板]Nim游戏

题目描述

甲,乙两个人玩Nim取石子游戏。
nim游戏的规则是这样的:地上有n堆石子(每堆石子数量小于10000),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取完,不能不取。每次只能从一堆里取。最后没石子可取的人就输了。假如甲是先手,且告诉你这n堆石子的数量,他想知道是否存在先手必胜的策略。

结论:所有石子异或和为0则先手必败

证明:

(1):输的状态最后肯定是每堆都没有石子,此时所有石子异或和为(0^0^0^0......^0 = 0)

(2):我们设所有石子的异或和为(k)(k)的最高位为第(i)位,则其中必定有一堆石子的第(i)位为(i)(异或的性质),我们设这堆石子为(H),其余所有石子异或和为(x),那么(H)$x$$=$$k$,那么有$H$(k)(=)(x),所以((H)$k$)(x)(=)(0)

(3):所以我们得出:如果先手异或和不为(0),可以一步让后手的情况为异或和为(0);如果先手异或和为(0),那么后手异或和就不为(0)

(4):现在假设开始时所有石子的异或和不为(0),则先手可以一直让后手的异或和为(0)(也就是(2)中的操作),最终后手会走向所有石子都是(0)的情况,则后手败,反之开始时所有石子的异或和为(0),那么后手也可以使得先手的异或和一直为(0),那么先手最终会走向所有石子都是(0)的情况,则先手败。

所以结论得以证明。

#include <cstdio>
#include <iostream>
using namespace std;
int T,n,ans;
int main()
{
	scanf("%d",&T);
	while(T --)
	{
		scanf("%d",&n);
		ans = 0;
		for(int i=1;i<=n;i++)
		{
			int x;
			scanf("%d",&x);
        	ans ^= x;
		}
		if(ans)
			printf("Yes
");
    	else printf("No
");
	}
	return 0;
}
原文地址:https://www.cnblogs.com/-Wind-/p/11830368.html