来源:
ACM Short Term Exam_2007/12/13
题目大意:
Nim游戏的一个变形,给定三堆棋子,每次只能从其中一堆取,取的个数为Fibonacci数列中的任意一项。
思路:
首先递推求出Fibonacci数列的前1000项,然后构造SG函数$sg[i]=mex{sg[j]|j为i的后继状态}$。
答案即为三者SG函数的异或。
1 #include<cstdio> 2 #include<cctype> 3 #include<cstring> 4 inline int getint() { 5 char ch; 6 while(!isdigit(ch=getchar())); 7 int x=ch^'0'; 8 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 9 return x; 10 } 11 const int N=1001; 12 int f[N]={1,1},sg[N]; 13 bool hash[N]; 14 int main() { 15 for(int i=2;i<N;i++) f[i]=f[i-2]+f[i-1]; 16 for(int i=1;i<N;i++) { 17 memset(hash,0,sizeof hash); 18 for(int j=1;f[j]<=i;j++) hash[sg[i-f[j]]]=true; 19 for(int j=0;j<N;j++) { 20 if(!hash[j]) { 21 sg[i]=j; 22 break; 23 } 24 } 25 } 26 for(int m=getint(),n=getint(),p=getint();m||n||p;m=getint(),n=getint(),p=getint()) { 27 puts(sg[m]^sg[n]^sg[p]?"Fibo":"Nacci"); 28 } 29 return 0; 30 }