类似尼姆博弈的题,如果理解尼姆博弈的过程还是不难想的
这道题在尼姆博弈的基础上加多了一个可以把一堆分成任意数目的两堆的操作
我们先把每一堆当成一个独立的游戏来看
然后用sg函数打表发现规律 一堆数目为n的石子 分成 x 和 y 的两堆,那么 这样可以得到 sg[x] ^ sg[y] 的值 注意不是 x ^ y而是 对应sg函数的值 然后枚举n可以到达的每种情况 就可以得到 n 的mex{}也就是sg[n]
用sg函数打表的代码 我是用递归的方法来写的
#include<bits/stdc++.h>
using namespace std;
const int N = 1005;
int sg[N],vis[N];
int f(int x)
{
if(sg[x]!=-1) return sg[x];
memset(vis,0,sizeof(vis));
for(int i=x;i>0;i--)
{
vis[f(x-i)]=1;
}
for(int i=1;i<=x/2;i++)
{
int t = f(i)^f(x-i);
vis[t]=1;
}
for(int i=0;;i++)
{
if(vis[i]==0)
{
return sg[x]=i;
}
}
}
int main()
{
memset(sg,-1,sizeof(sg));
sg[0]=0;
sg[1]=1;
for(int i=1;i<=20;i++)
{
cout<<i<<" "<<f(i)<<endl;
}
return 0;
}
打了前20的值 发现 3 和 4 , 7 和 8 ,11 和 12 , 15 和 16 的值有规律
然后发现 如果 n % 4 ==0 sg值为 n-1
如果 n%4==3 sg值为n+1;
其余的都为n
然后AC代码
int main()
{
int T;
cin>>T;
while(T--)
{
int n,x,ans = 0;
cin>>n;
for(int i=0;i<n;i++)
{
cin>>x;
if(x%4==0) ans^=(x-1);
else if(x%4==3) ans^=(x+1);
else ans^=x;
}
if(ans) cout<<"Alice";
else cout<<"Bob";
cout<<endl;
}
return 0;
}
大二 第一篇博客