HDU-1848 Fibonacci again and again
题目大意
有
3
堆石子,分别有
Sample Input
1 1 1
1 4 1
0 0 0
Sample Output
Fibo
Nacci
思路
这篇博文通过实例很清楚的介绍了基础的 SG函数 求法(可能是没看到别的吧。。。),感觉已经明白了 SG函数 的定义和计算方法。
设运算
mex(minimalexcludant)
是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。
若状态
S
能到达状态
SG函数
性质:
①对于任意的局面,如果它的
SG
值为
0
,那么它的任何一个后继局面的
②对于任意的局面,如果它的
在我们每次只能进行一步操作的情况下,对于任何的游戏的和,我们若将其中的任一单一
SG−组合游戏
换成数目为它的
SG
值的一堆石子,该单一
SG−组合游戏
的规则变成取石子游戏的规则(可以任意取,甚至取完),则游戏的和的胜负情况不变。
实际运用起来就是将组合游戏看成尼姆博弈,将所有的 SG 值异或起来判断组合游戏的胜负。
代码
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
int n,m,p,ans;
int f[55],cnt,sg[1005];
bool vis[1005];
void init() {
f[1]=f[2]=1;
cnt=2;
while(f[cnt]<1000) {
f[cnt+1]=f[cnt]+f[cnt-1];
++cnt;
}
}
void getSG(int mx) {
sg[0]=0;
for(int i=1;i<=mx;++i) {
memset(vis,false,sizeof(vis));
for(int j=1;f[j]<=i;++j) {
vis[sg[i-f[j]]]=1;
}
for(int j=0;j<=i;++j) {
if(!vis[j]) {
sg[i]=j;
break;
}
}
}
}
int main() {
init();
getSG(1000);
while(scanf("%d%d%d",&m,&n,&p),m!=0||n!=0||p!=0) {
printf("%s\n",(sg[m]^sg[n]^sg[p])==0?"Nacci":"Fibo");
}
return 0;
}