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

欢迎大家访问我的老师的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 sum=A1xorA2xorA3xorA4xorxorAn

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

根据NIM博弈证明的 A i xor ⁡ x < A i A_i\operatorname{xor}x<A_i Aixorx<Ai时,我们就能从 A i A_i Ai堆中取走若干石子,使其变成 A i xor ⁡ x A_i\operatorname{xor}x Aixorx,使得 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 A1xorA2xorxorAixorxxorAn=xxorx=0,从而得到了一个各堆石子数异或起来等于 0 0 0的局面。

AC code

#include
#include
#include
#include
#include
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;
}

你可能感兴趣的:(caioj数论,博弈SG)