一.题目链接:

HDU-1848

二.题目大意:

有三堆石子,石子个数分别为 m, n, p

两个人玩游戏,规则如下:

两个人轮流取石子,每次选择一堆石子,取的个数必须为斐波那契数列的项

最先取光所有石子的人获胜.

三.分析:

没啥好分析的,就是一道 SG 函数水题.

附上博弈学习的链接

转载 - 1

转载 - 2

四.代码实现:

#include <set>
#include <map>
#include <ctime>
#include <queue>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <ctime>
#define eps 1e-6
#define pi acos(-1.0)
#define ll long long int
using namespace std;

const int M = 1000;
int fib[20];
int sg[M + 5];
bool vis[M + 5];

void init()
{
    fib[1] = 1;
    fib[2] = 1;
    for(int i = 3; ; ++i)
    {
        fib[i] = fib[i - 1] + fib[i - 2];
        if(fib[i] > M)
            break;
    }
    memset(sg, 0, sizeof(sg));
    for(int i = 1; i <= M; ++i)
    {
        memset(vis, 0, sizeof(vis));
        for(int j = 1; fib[j] <= i && fib[j] <= M; ++j)
            vis[sg[i - fib[j]]] = 1;
        for(int j = 0; ; ++j)
        {
            if(!vis[j])
            {
                sg[i] = j;
                break;
            }
        }
    }
}

int main()
{
    init();
    int m, n, p;
    while(~scanf("%d %d %d", &m, &n, &p))
    {
        if(m + n + p == 0)
            break;
        if(sg[n] ^ sg[m] ^ sg[p])
            printf("Fibo\n");
        else
            printf("Nacci\n");
    }
    return 0;
}