题目:
一个小游戏,定义如下:
1、 这是一个二人游戏;
2、 一共有3堆石子,数量分别是m, n, p个;
3、 两人轮流走;
4、 每走一步可以选择任意一堆石子,然后取走f个;
5、 f只能是菲波那契数列中的元素(即每次只能取1,2,3,5,8…等数量);
6、 最先取光所有石子的人为胜者;
假设双方都使用最优策略,请判断先手的人会赢还是后手的人会赢。
思路:求sg值
代码:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<algorithm>
#include<ctime>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<string>
#include<vector>
#include<map>
#include<set>
#include<queue>
#include<stack>
#include<list>
#include<numeric>
using namespace std;
#define LL long long
#define ULL unsigned long long
#define INF 0x3f3f3f3f
#define mm(a,b) memset(a,b,sizeof(a))
#define PP puts("*********************");
template<class T> T f_abs(T a){ return a > 0 ? a : -a; }
template<class T> T gcd(T a, T b){ return b ? gcd(b, a%b) : a; }
template<class T> T lcm(T a,T b){return a/gcd(a,b)*b;}
// 0x3f3f3f3f3f3f3f3f
//0x3f3f3f3f
const int maxn=1e3+50;
int fib[25];
int sg[maxn];
bool mex[4*maxn];
void init_sg(int n){
for(int i=0;i<=n;i++){
mm(mex,false);
for(int j=1;j<=20;j++){
int x=fib[j];
if(i>=x)
mex[sg[i-x]]=true;
else
break;
}
for(int j=0;;j++)
if(!mex[j]){
sg[i]=j;
break;
}
}
}
int main(){
int m,n,p;
fib[1]=1;
fib[2]=2;
for(int i=3;i<=20;i++)
fib[i]=fib[i-1]+fib[i-2];
init_sg(1000);
while(~scanf("%d%d%d",&m,&n,&p)){
if(m==0&&n==0&&p==0)
break;
int SG=(sg[m]^sg[n]^sg[p]);
if(SG>0) printf("Fibo\n");
else printf("Nacci\n");
}
return 0;
}