Fibonacci博弈原理与证明
简介
Fibonacci博弈的定义是:
有一堆物品,两人轮流取,先手第一次可以取任意个但不能全部取完。之后每次取的数量必须大于等于 \(1\) 且小于等于上次取的数量的两倍,最后把物品全部取完者胜利
现在给出初始的物品数 \(n\) ,判断先手是否有必胜策略
推理
设 \(f(i)\) 表示斐波那契数列的第 \(i\) 项
证明:当 \(n\) 为大于等于 \(2\) 的斐波那契数时先手必败
-
\(n=2\) 时,显然先手必败
-
若 \(n\leq f(k)\) 且为斐波那契数时,先手必败
那么 \(n=f(k+1)\) 时,先手第一次不能拿大于等于 \(f(k-1)\) 个物品,如果这样,那么第一次拿完后剩余的物品数为:
\[n^{'}\leq f(k+1)-f(k-1)=f(k)=f(k-1)+f(k-2)\leq 2f(k-1) \]那么后手在第二次可以直接取得胜利,因此先手第一次拿的物品必须小于 \(f(k-1)\)
把 \(f(k-1)\) 看作一个子游戏,由假设可得后手可以恰好把 \(f(k-1)\) 取完,那么现在游戏只剩 \(f(k)\) 个物品,由假设得先手必败
综上,\(n\) 为斐波那契数时先手必败
接下来我们证明: \(n\) 不为斐波那契数时先手必胜
首先引入 齐肯多夫定理 :任何整数都可以被分解成若干个不连续的斐波那契数之和
证明:
-
\(n=1,2,3\) 时,\(f(2)=1,f(3)=2,f(4)=3\) 命题成立
-
若 \(n\leq k\) 时命题都成立
那么 \(n=k+1\) 时,若 \(n\) 为斐波那契数,命题成立
\(n\) 不是斐波那契数时,设 \(f(m)<n<f(m+1),n^{'}=n-f(m)\) ,则有:
\[n^{'}<f(m+1)-f(m)=f(m-1)<n \]所以 \(n^{'}\) 可以用不连续的斐波那契数之和表示,设表示中最大的一项斐波那契数为 \(f(a)\) 则有 \(f(a)\leq n^{'}<f(m-1),a<m-1\) ,所以 \(a\) 和 \(m\) 不是连续整数
\(n=f(m)+n^{'}=f(m)+f(a)+\cdots\) 也符合条件,命题成立
当 \(n\) 不为斐波那契数时,设 \(n=f(a_1)+f(a_2)+\cdots+f(a_p)\) ,数列单调递减且不为连续整数,那么先手取 \(f(a_p)\) 时,由于 \(a_p\leq a_{p-1}-2\) ,所以有:
当且仅当 \(a_p=1,a_{p-1}=3\) 时取等号
此时若数列每项差值都为 \(2\) ,那么数列的形式即为:
易证 \(n=f(1)+f(3)+\cdots+f(2x-1)=f(2x)\) 与假设不为斐波那契数矛盾
那么必然存在 \(k\) 使 \(a_k-a_{k+1}\geq 3\) 且 \(\forall i>k,a_i-a_{i+1}=2\) ,可以将 \(f(a_{k+1})+f(a_{k+2})+\cdots+f(a_p)\) 变为 \(f(a_{k+1}+1)\) 而 \((a_{k+1}+1)+2\leq a_k\) 满足不连续整数的限制,\(n\) 可以写作:
所以可以把这种情况转化为下面讨论的不取等号的情况
不取等号时,后手只能取 \(f(a_{p-1})\) 的一部分,将视角转移到后手上,这就相当于一个 \(n=f(a_{p-1})\) 的子游戏,而按照之前证明的,后手作为子游戏的先手必败,那么先手恰好可以拿完 \(f(a_{p-1})\) ,以此类推,每一项斐波那契数都会由先手拿完,先手一定胜利
代码
#include<bits/stdc++.h>
using namespace std;
int f[200 + 5];
map<int, bool> mp;
int main()
{
f[1] = f[2] = 1;
for(int i = 3; i <= 50; i++) {
f[i] = f[i - 1] + f[i - 2];
mp[f[i]] = true;
}
int x;
while(scanf("%d", &x) != EOF && x)
printf("%s\n", mp[x] ? "Second win" : "First win");
return 0;
}