标签:
2 3 2 2 3 2 3 3
Alice Bob
有两个人Alice 和 Bob在玩一个游戏,游戏的内容就是一共有 m 堆石子,每个人有两种操作:
1.可以拿每一堆的任意数量但不能不拿;
2.可以将当前一堆的石子(当前的石子数肯定是>=2的)变为两堆;
最后谁先拿完谁赢,Alice 先手
解题思路:
首先我们看一下数据范围,S[i]<2^31-1,所以我们不能直接用SG函数,但是我们可以先进行打表,然后看一下有没有什么规律,首先我们分析一下,如果没有后边的第二种操作那么这就是一个简单的尼姆博弈,就是求一个异或值就行了,那么加上第二种操作,那么就考虑一下它的后继状态,他的后即状态,SG[i] = mex{i-1,i-2... SG[i-1]^SG[1],SG[i-2]^SG[2]};所以我们就可以通过这个后继状态来打一个表,通过这个表我们找到了一些规律,就是当x%4==0的时候,SG[x] = x-1,当x%4==3的时候,SG[x] = x+1,其他情况就是SG[x] = x;
My Code:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN = 1e3+5;
int sg[MAXN];
int get_SG(int x)
{
if(sg[x]!=-1)
return sg[x];
int hash[MAXN];
memset(hash, 0, sizeof(hash));
for(int i=x-1;i>=0;i--)
hash[get_SG(i)]=1;
for(int j=1; j<=x/2; j++)
hash[get_SG(x-j)^get_SG(j)]=1;
int k;
for(k=0; k<MAXN; k++)
{
if(!hash[k])
{
return sg[x] = k;
}
}
}
int main()
{
/**测试打表**/
/*
memset(sg,-1,sizeof(sg));
for(int i=0; i<50; i++)
{
printf("sg[%d] = %d\n",i,get_SG(i));
}*/
int T;
cin>>T;
while(T--)
{
int m;
int ans = 0;
cin>>m;
while(m--)
{
int x;
cin>>x;
if(x%4==0)
ans ^= (x-1);
else if(x%4 == 3)
ans ^= (x+1);
else
ans ^= x;
}
if(ans)
puts("Alice");
else
puts("Bob");
}
return 0;
}
HDU 3032 Nim or not Nim?(博弈 SG打表找规律)
标签:
原文地址:http://blog.csdn.net/qingshui23/article/details/51203593