hdu 2516 取石子游戏

题目:hdu 2516 取石子游戏

思路:Fibonacci Nim

枚举前几项,发现2,3,5是必败态,不能说明什么。对于当前的状态,第一次不能全部取完,其余的每次取的时候,不能超过前者上一次的两倍。

对于当前状态n,最多能取的是 ceil(n/3)-1 和 前一状态取的的两倍 两者间的最小值。

然后这里有个齐肯多夫定理:任何一个正整数都可以表示成若干个不连续斐波那契项的和。

若是当前状态时斐波那契项会怎么样,分析一下斐波那契项,F(n)=F(n-1)+F(n-2)=2*F(n-2)+F(n-3)<=2*F(n-2)+F(n-2)-1  所以ceil(F(n)/3)-1 < =F(n-2)-1 

如果对手取F(n-2)-1 剩下 F(n)-F(n-2)+1=F(n-1)+1 或者取其他的,都不会让剩下的是非波纳契项。

也就是说,在保证取得数字大小在范围之内的前提下,我们可以控制对手的状态一直是斐波那契项,已知前几项2,3,5是必败态,可以推导一下,发现斐波那契项均是必败态。

对于不是斐波那契数列的,根据齐肯多夫定理,可以表示成若干不连续斐波那契项的和,那么不管对手怎么取,我们要做的就是取若干石子,使剩下的状态呈现为一个非波纳契项。

具体证明请看这里:http://yjq24.blogbus.com/logs/46150651.html


#include <cstring>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <cstdio>
#include <vector>
#include <set>
using namespace std;
set<int>s;
int main()
{
    s.clear();
    int x=1,y=1,tmp=x+y;
    while(tmp>0)
    {
        s.insert(tmp);
        x=y;
        y=tmp;
        tmp=x+y;
    }
    int n;
    while(scanf("%d",&n),n)
    {
        if(s.count(n))
            printf("Second win\n");
        else
            printf("First win\n");
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值