【HDU1848】Fibonacci again and again(博弈论)

题面

Hdu
你有三堆石子,每堆石子的个数是 n,m,p n , m , p ,你每次可以从一堆石子中取走斐波那契数列中一个元素等数量的石子数,两人轮流取,不能操作者输,判定先后手的胜利。

题解

根据 SG S G 定理,三堆石子可以拆开来看,最终状态的 SG S G 函数为这三堆石子 SG S G 函数的异或值。
那么,我们只需要预处理任意数量石子的 SG S G 值就好了。
对于一堆数量为 x x 的石子的SG函数为:

SG(x)=mex{SG(xy),yFib,xy} S G ( x ) = m e x { S G ( x − y ) , y ∈ F i b , x ≥ y }

直接预处理即可。

#include<iostream>
using namespace std;
int fib[20],n,m,p,SG[1010];
bool vis[1010];
int main()
{
    ios::sync_with_stdio(false);
    fib[1]=fib[2]=1;SG[0]=0;
    for(int i=3;i<=17;++i)fib[i]=fib[i-1]+fib[i-2];
    for(int i=1;i<=1000;++i)
    {
        for(int j=1;fib[j]<=i;++j)vis[SG[i-fib[j]]]=true;
        for(int j=0;;++j)if(!vis[j]){SG[i]=j;break;}
        for(int j=1;fib[j]<=i;++j)vis[SG[i-fib[j]]]=false;
    }
    while(233)
    {
        cin>>n>>m>>p;if(!n&&!m&&!p)break;
        if(SG[n]^SG[m]^SG[p])cout<<"Fibo"<<endl;
        else cout<<"Nacci"<<endl;
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值