(HDU - 2176)取(m堆)石子游戏(尼姆博弈)

Posted AC__dream

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(HDU - 2176)取(m堆)石子游戏(尼姆博弈)相关的知识,希望对你有一定的参考价值。

题目链接:取(m堆)石子游戏 - HDU 2176 - Virtual Judge (ppsucxtt.cn)

这道题目考察的还是对尼姆博弈的理解,一开始给定n堆石子,我们将n堆石子数目进行异或,当异或值为0时先手必败,反之先手必胜,如果n堆石子的数目异或值不为0,先手的操作目的就是使其异或值重新归0来使后手进入必败态,不妨假设n堆石子的数目分别为a1,a2,a3,……,an,设a1^a2^a3^……^an=k,则有a1^a2^a3^……^an^k=k^k=0,而我们的具体操作就是选择一堆石子ai,将其数目与k进行异或,并将其值变为ai^k即可,那结合实际情况易知,ai^k<ai,所以对于本题中所问的先手的选择总数就是看有多少个ai满足ai^k<ai,对于每堆满足ai^k<ai的石子我们都可以把ai变成ai^k来使得n堆石子异或值为0,也就是输出ai和ai^k,

下面是代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int N=1e6+10;
int a[N];
int main()
{
	int n;
	while(1)
	{
		scanf("%d",&n);
		if(n==0) break;
		int ans=0;
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&a[i]);
			ans^=a[i]; 
		}
		if(ans==0) puts("NO");
		else
		{
			bool flag=false;
			for(int i=1;i<=n;i++)
				if((ans^a[i])<a[i])
				{
					if(!flag)
					{
						flag=true;
						puts("Yes");
					} 
					printf("%d %d\\n",a[i],ans^a[i]);
				}
		}
	}
	return 0;
}

以上是关于(HDU - 2176)取(m堆)石子游戏(尼姆博弈)的主要内容,如果未能解决你的问题,请参考以下文章

HDU 2176 取(m堆)石子游戏 尼姆博弈

ACM-尼姆博弈之取(m堆)石子游戏——hdu2176

HDU 2176 取(m堆)石子游戏 && HDU1850 Being a Good Boy in Spring Festivaly

HDU 2176 取(m堆)石子游戏 博弈

取(m堆)石子游戏 HDU2176(Nim博弈)

杭电acm 2176 取(m堆)石子游戏 (Nim游戏)