您的位置:首页 > 其它

UVA 1378 A Funny Stone Game (经典博弈)

2017-03-03 19:44 483 查看
题目传送门


代码不是关键,关键的是对博弈和sg函数的理解。重点是在构造sg函数的时候是将一个石头看成一个堆,所以按照sg函数的定义后继状态为两个石头构成的堆。然后根据对称性原理和xor的性质,在某个堆,只有石头个数为奇数时才会对参与xor,才会对最后答案有贡献。

最后枚举第一步操作的可能性使得xor为0即转入必败态。此时相当于去掉第i个堆里的一个石头,在第j堆和第k堆加上个一块石头。

#include <bits/stdc++.h>
using namespace std;

const int N=100005;
int vis[80],sg[30],num[30];
int init()
{
sg[1]=0;
for(int i=2;i<=23;i++)
{
memset(vis,0,sizeof(vis));
for(int j=1;j<i;j++)
{
for(int k=1;k<=j;k++)
{
vis[sg[j]^sg[k]]=1;
}
}
for(int q=0;q<80;q++)
{
if(!vis[q])
{
sg[i]=q;
break;
}
}
}
return 0;
}

int main()
{
int n,t=0;
init();
while(scanf("%d",&n)!=EOF)
{
int ans=0;
if(!n) break;
for(int i=1;i<=n;i++)
{
scanf("%d",&num[i]);
if(num[i]&1)
{
ans^=sg[n+1-i];
}
}
cout<<ans<<endl;
printf("Game %d: ",++t);
if(!ans)
{
printf("-1 -1 -1\n");
continue;
}
int flag=1;
for(int i=1;i<=n&&flag;i++)
{
if(num[i])
for(int j=i+1;j<=n&&flag;j++)
{
for(int k=j;k<=n&&flag;k++)
{
if((ans^sg[n+1-i]^sg[n+1-j]^sg[n+1-k])==0)
{
printf("%d %d %d\n",i-1,j-1,k-1);
flag=0;
}
}
}
}

}
return 0;
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  博弈