斐波那契博弈

母题:有一堆个数为n的石子,游戏双方轮流取石子,满足:
1)先手不能在第一次把所有的石子取完;
2)之后每次可以取的石子数介于1到对手刚取的石子数的2倍之间(包含1和对手刚取的石子数的2倍)。
这种博弈题麻烦的地方是每次走的步数限制是动态的,是根据上一步对手走的步数来推断,这里必须要引入一个定理:齐肯多夫定理

任何正整数都可以表示成若干个不连续的斐波那契数之和。这种和式称为齐肯多夫表述法。

也就是说,每个数都能有不连续的斐波那契数来表示。
我们以83为例:83被夹在55和89之间,所以83=55+28,28被夹在21和34之间,28=21+7,7=5+2。这样分解的意义是,假设先手先取走2,那么后手最多取走1~4,假设他取走4,那么你就能取走1。然后他取走2,你取走4,他取走8,你取走7。总之,进过几轮,你都能取走剩下的数,使之保持为一个斐波那契数。所以先手一定赢
我们再以89为例:89=55+34,假如先取的数大于等于34,那么剩下的55<34*2,所以后手胜,假如说取的数y< = 34,那么剩下的数x在55到89之间,x=55+a1+a2+..+an,当an < =2y时,根据之前的分析,就能获得先手胜的局面
例:取石子游戏(hud 2516)
Problem Description
1堆石子有n个,两人轮流取.先取者第1次可以取任意多个,但不能全部取完.以后每次取的石子数不能超过上次取子数的2倍。取完者胜.先取者负输出”Second win”.先取者胜输出”First win”.

Input
输入有多组.每组第1行是2<=n<2^31. n=0退出.

Output
先取者负输出”Second win”. 先取者胜输出”First win”.
参看Sample Output.

Sample Input
2
13
10000
0

Sample Output
Second win
Second win
First win

因为没有规定先手第一次取多少,所以不用判断n为斐波那契数时的先手胜的情况
AC代码:

#include<bits/stdc++.h>
using namespace std;
using LL =int64_t;
LL fib[55] ;
void init() {
    fib[1]=1,fib[2]=1;
    for(int i=3;i<=50;i++) fib[i]=fib[i-1]+fib[i-2];
}
int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    LL n;
    init();
    while(cin>>n&&n) {
        for(int i=1;i<=50;i++) {
            if(fib[i]==n) {
                    cout<<"Second win"<<endl;
                    break;
            }
            else if(fib[i]>n) {
                    cout<<"First win"<<endl;
                    break;
            }
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值