斐波那契博弈

斐波那契博弈

题目

一堆石子有n个,两人轮流取,先取者第1次可以取任意多个,但不能全部取完,以后每次取的石子数不能超过上次取子数的2倍。先取完者胜(n>1)。

输入示例

输入: 89
输出: false
解释: 无论你怎么取,都是对方赢

解题思路

注:这个跟威佐夫博弈的区别,就是游戏规则的动态化,一方每次可以取的石子数依赖于对手刚才取的石子数。

这个题的奇异局势是:当nFibonacci数列时,先手败。

这里需要引入数论的一个定理:任何正整数都可以表示为若干个不连续的斐波那契数之和

证明:分解的思想是尽可能分解成大的Fibonacci数。

(1) 齐肯多夫定理--斐波那契数列_MaxMercer的博客-CSDN博客_齐肯多夫定理

例子:

  • n取89时,n 是 Fibonacci
  • 如果先手y取值不小于34,后手直接取完。
  • 当先手y小于34时,剩下的石头x在55到89之间。
  • x肯定不是Fibonacci数,将x分解,\(x=55+f[i]+…+f[j](55>f[i]>...>f[j])\)
  • 此时后手取f[j]就行(下面证明\(f[j]\le 2y\)),说明对手总能取到每一堆分解数的最后一个,所以对手胜利。

反证法:\(f[j]\le 2y\)

假设\(f[j] > 2y\) ,则 \(y < \frac{f[j]}{2} = \frac{f[j-1]+f[j-2]}{2} < f[j-1]\)

而最初的石子数是个斐波那契数,即 :

\[n = f[k] = x + y < f[k-1] + f[i] + … + f[j] + f[j-1] ≤ f[k-1]+f[i]+f[i-1] ≤ f[k-1]+f[k-2] ≤ f[k] \tag{1} \]

注意:第一个不等号是严格,矛盾!\(f[j] ≤ 2y\)得证。

代码

public boolean helper(int n){ 
    int f1=1;
    int f2=2;
    int f3=3;
    while(n>=f3)
    {
        f3=f1+f2;
        if(f3==n) return false;
        f1=f2;
        f2=f3;
    }
    return true;
}
posted @ 2022-04-05 15:13  LibraXiong  阅读(128)  评论(0)    收藏  举报