巴什博弈(Bash Game)
定义:只有一堆石子,两人轮流取,最少取一个,最多取m个,最后去完者为胜。
思考:
①当石子个数n=0时为必败点;(根据题意得来)
②当石子个数0<n<=m时为必胜点;(可以到达状态①)
③当石子个数n=m+1时为必败点;(只能到达状态②)
④当石子个数m+1<n<=(m+1)+m时为必胜点;(可以到达状态③)
⑤当石子个数n=(m+1)+m+1时为必败点;(只能到达状态④)
……
当n为m+1的整数倍时为必败点
把n写成这样的格式:n=r*(m+1)+s;
只要s不为0,即可胜。
思路:对于每个堆来说最少取一个,最多取l个,这是一个典型的巴什博弈模型,所以最后决定胜败的只取决于a[i]%(l+1)的值,为0则表示必败,否则必胜。
由于总共有n堆,每次最多只能取m堆进行操作。所以上面的模型可以转换成为nim game。本来如果没有m堆这个条件,直接a[1]^a[2]......^a[n]即可
但现在(创新)可以这么做,其实异或只是每个位的半加运算,现在把每一位都加起来。mod (m+1)不就可以了。(虽然我不知到为什么这样就可以了,以后讨论吧,先记住结论)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
using namespace std;
const double pi=acos(-1.0);
int s[50],xr[50];
int n,l,m,r;
int solve()
{
double c=2*pi*r;
l=(l/c)+1;
//cout<<l<<endl;
memset(xr,0,sizeof(xr));
for(int i=1;i<=n;i++)
{
s[i]=(s[i]/c)+1;
s[i]%=l;
for(int j=1,g=s[i];g;g>>=1,j++)
{
xr[j]+=(g&1);
}
}
for(int i=1;i<=30;i++)
{
if(xr[i]%(m+1))
return 1;
}
return 0;
}
int main()
{
//freopen("t.txt","r",stdin);
while(scanf("%d%d%d%d",&n,&m,&l,&r)!=EOF)
{
for(int i=1;i<=n;i++) scanf("%d",&s[i]);
if(solve()) printf("Alice\n");
else printf("Bob\n");
}
return 0;
}