斐波那契博弈
斐波那契博弈
题目
一堆石子有n个,两人轮流取,先取者第1次可以取任意多个,但不能全部取完,以后每次取的石子数不能超过上次取子数的2倍。先取完者胜(n>1)。
输入示例
输入: 89
输出: false
解释: 无论你怎么取,都是对方赢
解题思路
注:这个跟威佐夫博弈的区别,就是游戏规则的动态化,一方每次可以取的石子数依赖于对手刚才取的石子数。
这个题的奇异局势是:当n为Fibonacci数列时,先手败。
这里需要引入数论的一个定理:任何正整数都可以表示为若干个不连续的斐波那契数之和。
证明:分解的思想是尽可能分解成大的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;
}

浙公网安备 33010602011771号