用当前人可以分配的球数就可以代表一个状态,开始Alice拿掉那个1个球的箱子后,剩下n个球由他来分配,分配为一多一少后,Bob所分配的球数是多的箱子中的数量。
即,球数n可以转化为(n+1)/2~n-1间的一个数。用这个规律递推SG值。SG(n)=除所有n能到达的状态的SG值以外,最小的非负整数。必败状态SG值为0,显然1是一个必败状态。SG值用记忆化搜索求出。
对前1000个数测试后发现SG值为0的数恰好是所有的2^n-1
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#include <set>
/*int SG[1000];
bool vis[1000];
int Find(int n){
if(vis[n]) return SG[n];
bool next[1000];
memset(next,0,sizeof(next));
for(int i=((n+1)/2);i<n;i++){
next[Find(i)]=1;
}
for(int i=0;i<=n;i++){
if(!next[i]){
SG[n]=i;
break;
}
}
vis[n]=1;
return SG[n];
}*/
int main(){
set <int> lose;
int cur=2;
for(int i=2;i<=29;i++){
cur*=2;
lose.insert(cur-1);
}
int N;
while(~scanf("%d",&N)){
if(!N) break;
if(lose.count(N)) printf("Bob\n");
else printf("Alice\n");
}
return 0;
}