博弈SG(模版):Nim取石子游戏[caioj1166]

版权声明:作为一个蒟蒻,转载时请通知我这个蒟蒻 https://blog.csdn.net/zyszlb2003/article/details/89843197

欢迎大家访问我的老师的OJ———caioj.cn

题面描述

传送门

思路

我们先得到
s u m = A 1 xor A 2 xor A 3 xor A 4 xor xor A n sum=A_1\operatorname{xor}A_2\operatorname{xor}A_3\operatorname{xor}A_4\operatorname{xor}\cdots\operatorname{xor}A_n

判断 s u m sum 是否为 0 0 ,若为 0 0 ,则先手输,反之,先手必赢。

根据NIM博弈证明 A i xor x < A i A_i\operatorname{xor}x<A_i 时,我们就能从 A i A_i 堆中取走若干石子,使其变成 A i xor x A_i\operatorname{xor}x ,使得 A 1 xor A 2 xor xor A i xor x xor A n = x xor x = 0 A_1\operatorname{xor}A_2\operatorname{xor}\cdots\operatorname{xor}A_i\operatorname{xor}x\operatorname{xor}\cdots A_n=x\operatorname{xor}x=0 ,从而得到了一个各堆石子数异或起来等于 0 0 的局面。

AC code

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstdlib>
using namespace std;
const int N=1e4+10;
int a[N],sum;
bool b[N];
int main()
{
	int n;
	while(scanf("%d",&n)!=EOF)
	{
		sum=0;
		for(int i=1;i<=n;i++)scanf("%d",&a[i]),sum^=a[i];
		if(!sum)
		{
			puts("First Lose");
		}
		else
		{
			puts("First Win");
			for(int i=1;i<=n;i++)
			{
				int k=sum^a[i];
				if(a[i]>=k)
					printf("%d %d\n",i,a[i]-k);
			}
		}
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zyszlb2003/article/details/89843197