閱讀533 返回首頁    go 阿裏雲 go 技術社區[雲棲]


zoj 2290 GAME 博弈

轉的 一篇非常好的分析 https://www.stubc.com/thread-3747-1-1.html

A必輸的情形形成菲波那契數列。

顯然,2和3是A必輸的情形。現在,設a和a[i+1]是連續兩個A必輸的狀態,則a[i+2]=a

+a[i+1]也是A必輸的狀態。因為,根據菲波那契數列的特點,A不能一次取a個以上

(含a個),否則,因為a[i+1]<2*a,B可以一次把剩下的全取完(不超過a[i+1]塊)。



剩下的問題就是,B能否在留下a[i+1]塊stones的同時,保證A不能一次性拿完剩下的所有

stones。如果成立的話,這就回到了a[i+1]的狀態。我們假設,對於a塊stones,B可以

保證最後一把不會超過a[i-1](2和3時都成立),而a[i+1](=a+a[i-1])>2*a[i-1]。

這就保證了剩下的a[i+1]塊石頭不會被A一次取完。注意到這時,B最後一把不會超過a[i+

1],其實也就歸納的證明了剛才的假設。



上述的證明其實也提示了A贏的情況下的策略。這也是一個遞歸的結果。設有n(n不是菲波

那契數)塊stones,離它最近而比它小的菲波那契數是a。A拿掉n-a塊後,留下a塊給B先拿

,A就贏了。令n=n-a。若n是菲波那契數,則A必須一次性取n塊。否則,重複上麵過程,直

到n為菲波那契數(包括1)為止。


/*
author:jxy
lang:C/C++
university:China,Xidian University
**If you need to reprint,please indicate the source**
*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
int fib[45];
int is_that(int re)
{
    int i=0;
    while(fib[i]<re)i++;
    if(fib[i]==re)return re;
    else return is_that(re-fib[i-1]);
}
int main()
{
    int i;
    fib[0]=1;fib[1]=1;
    for(i=2;i<45;i++)
        fib[i]=fib[i-1]+fib[i-2];
    int n;
    while(~scanf("%d",&n))
    {
        i=0;
        while(fib[i]<n)i++;
        if(fib[i]==n)puts("lose");
        else printf("%d\n",is_that(n-fib[i-1]));
    }

}


最後更新:2017-04-03 14:53:53

  上一篇:go URAL 1456 求a模n的階
  下一篇:go 網絡子係統37_網橋、端口定時器