HDU-1848-Fibonacci again and again(SG函数,博弈)

链接:

http://acm.hdu.edu.cn/showproblem.php?pid=1848

题意:

任何一个大学生对菲波那契数列(Fibonacci numbers)应该都不会陌生,它是这样定义的:
F(1)=1;
F(2)=2;
F(n)=F(n-1)+F(n-2)(n>=3);
所以,1,2,3,5,8,13……就是菲波那契数列。
在HDOJ上有不少相关的题目,比如1005 Fibonacci again就是曾经的浙江省赛题。
今天,又一个关于Fibonacci的题目出现了,它是一个小游戏,定义如下:
1、 这是一个二人游戏;
2、 一共有3堆石子,数量分别是m, n, p个;
3、 两人轮流走;
4、 每走一步可以选择任意一堆石子,然后取走f个;
5、 f只能是菲波那契数列中的元素(即每次只能取1,2,3,5,8…等数量);
6、 最先取光所有石子的人为胜者;

假设双方都使用最优策略,请判断先手的人会赢还是后手的人会赢。

思路:

求出SG函数,判断

代码:

// #include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<vector>
#include<string.h>
#include<set>
#include<queue>
#include<algorithm>
#include<math.h>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
const int MOD = 1e9;
const int MAXN = 1e3+10;

int Vis[MAXN], Sg[MAXN];
int F[MAXN];
int n, m, p;


int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);
    F[1] = 1, F[2] = 2;
    for (int i = 3;F[i-1] <= 1000;i++)
        F[i] = F[i-1]+F[i-2];
    Sg[0] = 0;
    for (int i = 1;i <= 1000;i++)
    {
        memset(Vis, 0, sizeof(Vis));
        for (int j = 1;F[j] <= i;j++)
            Vis[Sg[i-F[j]]] = 1;
        for (int j = 0;;j++) if (Vis[j] == 0)
        {
            Sg[i] = j;
            break;
        }
    }
    while(~scanf("%d%d%d", &n, &m, &p) && n)
    {
        if ((Sg[n]^Sg[m]^Sg[p]) == 0)
            puts("Nacci");
        else
            puts("Fibo");
    }

    return 0;
}

猜你喜欢

转载自www.cnblogs.com/YDDDD/p/12064603.html