HDU 1848 Fibonacci again and again(博弈)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1848

题意:游戏规则如下:

1、  这是一个二人游戏;
2、  一共有3堆石子,数量分别是m, n, p个;
3、  两人轮流走;
4、  每走一步可以选择任意一堆石子,然后取走f个;
5、  f只能是菲波那契数列中的元素(即每次只能取1,2,3,5,8…等数量);
6、  最先取光所有石子的人为胜者;

思路:我们需要找到一个新的函数f,对于局面 S=(a1,a2,a3,……an),#S=f(a1)+f(a2)+……+f(an)。若#S不等于0,则先手必胜,否则后手必胜。得到的结论是:设$S(x)表示x的下一步所有可能的局面,$S(x)={S1,S2,……Sk},g(x)={#S1,#S2,……,#Sk}。那么f(x)=mex{g(x)},也就是这样的f满足#S=0,则对于S的任意后继状态T,#T!=0;#S!=0,则存在一个后继T,#T=0。

 

 #include <iostream>

 #include <cstdio>

 #include <vector>

 #include <string.h>

 using namespace std;

 

 int n,m,p;

 int f[1005];

 

 void init()

 {

     vector<int> V;

     int i,j;

     V.push_back(1);

     V.push_back(2);

     while(V[V.size()-1]<=1000)

     {

         i=V[V.size()-1];

         j=V[V.size()-2];

         V.push_back(i+j);

     }

     f[0]=0;

     f[1]=1;

     int visit[1005];

     for(i=2;i<=1000;i++)

     {

         memset(visit,0,sizeof(visit));

         for(j=0;j<V.size()&&V[j]<=i;j++)

         {

             visit[f[i-V[j]]]=1;

         }

         for(j=0;visit[j];j++);

         f[i]=j;

     }

 }

 

 int main()

 {

     init();

     while(scanf("%d%d%d",&m,&n,&p),m||n||p)

     {

         int x=f[m]^f[n]^f[p];

         if(x) puts("Fibo");

         else puts("Nacci");

     }

     return 0;

 }

  

 

你可能感兴趣的:(fibonacci)