【算法】经典博弈论问题——斐波那契博弈 + Zeckendorf 定理 python

目录


斐波那契博弈(Fibonacci Nim)

先说结论:当初始石子数目 n 是斐波那契数时,先手必败;否则,先手有策略获胜。

证明概要:
当n=2时,先手只能取1颗石子,后手直接取剩下的1颗石子获胜,因此先手必败。
假设对于所有小于等于某个斐波那契数 f[k]的情况,结论都成立。
归纳:
对于f[k+1]=f[k]+f[k-1]的情况,可以把这一堆石子看成两堆,分别有f[k]和[k-1]颗石子。
根据归纳假设,无论先手怎么取,后手总能取到最后一个石子。
特别地,如果先手取的石子数大于等于f[k-1],则后手可以直接取完f[k],因为f[k]<2*f[k-1]。


齐肯多夫(Zeckendorf)定理

任何正整数都可以表示成若干个不连续的斐波那契数之和。

证明略


非斐波那契数的情况:

使用齐肯多夫定理(Zeckendorf's theorem),任何正整数可以表示为若干个不连续的斐波那契数之和。

将n分解为若干个不连续的斐波那契数之和,然后通过适当的策略让先手每次都能取到最后一颗石子,从而获胜。


示例分析

假设有一个 n=85 的石子堆,我们首先将85分解为斐波那契数之和:

85 = 55 + 30

30 = 21 + 9

9 = 8 + 1

所以,85=55+21+8+1。

根据上述结论,先手可以通过以下策略获胜:
1.先手先取1颗石子,剩下84颗。
2.因为84不是斐波那契数,后手无法直接应用斐波那契博弈的必败态。
3.接下来,先手可以根据后手的动作,逐步减少石子数,并确保每次后手面对的是非斐波那契数,最终达到胜利。


实战演练

[COCI 2010/2011 #4] HRPA https://www.luogu.com.cn/problem/P6487

题目描述

有 n n n 枚石子。两位玩家定了如下规则进行游戏:

  • Mirko 先取一次,Slavko 再取一次,然后 Mirko 再取一次,两人轮流取石子,以此类推;
  • Mirko 在第一次取石子时可以取走任意多个;
  • 接下来,每次至少要取走一个石子,最多取走上一次取的数量的 2 2 2 倍。当然,玩家取走的数量必须不大于目前场上剩余的石子数量。
  • 取走最后一块石子的玩家获胜。

双方都以最优策略取石子。Mirko 想知道,自己第一次至少要取走几颗石子最终才能够获胜。

输入格式

输入一行一个整数 n n n,表示石子的数量。

输出格式

输出一行一个整数,表示 Mirko 最少取多少石子可以保证获胜。

样例输入 #1

复制代码
4

样例输出 #1

复制代码
1

样例输入 #2

复制代码
7

样例输出 #2

复制代码
2

样例输入 #3

复制代码
8

样例输出 #3

复制代码
8

提示

样例 1 解释

对于这个样例,Mirko 第一次可以取 1 / 2 / 3 / 4 1/2/3/4 1/2/3/4 个。虽然他取 4 4 4 个会直接赢得比赛,但这并不是最少的。最少的方案是取走 1 1 1 个。这样 Slavko 只能取走 1 1 1 个或者 2 2 2 个。无论选择哪种,Mirko 下一步都能取走所有的石子并获胜。

数据规模与约定

对于 100 % 100\% 100% 的数据,保证 2 ≤ n ≤ 1 0 15 2\le n\le 10^{15} 2≤n≤1015。

说明

题目译自 COCI2010-2011 CONTEST #4 T6 HRPA


题解code:

python 复制代码
n = int(input())


def solve(n):
    if n == 1:
        return 1
    if n == 2:
        return 2
    a, b = 1, 2  # 初始化前两个斐波那契数
    while True:
        c = a + b  # 计算下一个斐波那契数
        if c == n:
            return n  # 当前n是斐波那契数,先手必败
        elif c > n:
            break  # 当前c大于n,退出循环
        a, b = b, c  # 更新a和b为下一个斐波那契数

    # 当前n不是斐波那契数,减去b并继续判断
    return solve(n - b)


print(solve(n))

END
如果有更多问题或需要进一步的帮助,可以在评论区留言讨论哦!
如果喜欢的话,请给博主点个关注 谢谢

相关推荐
_不会dp不改名_11 小时前
leetcode_146 LRU缓存
算法·leetcode·缓存
Z_z在努力11 小时前
【数据结构】队列(Queue)全面详解
java·开发语言·数据结构
岑梓铭12 小时前
《考研408数据结构》第二章《线性表(顺序表、链表)》复习笔记
数据结构·笔记·考研
唐叔在学习12 小时前
pip安装太慢?一键切换国内镜像源,速度飞起!
后端·python
Gz、12 小时前
Spring Boot 常用注解详解
spring boot·后端·python
起风了___12 小时前
Python 自动化下载夸克网盘分享文件:基于 Playwright 的完整实现(含登录态持久化与提取码处理)
后端·python
帅帅爱数学12 小时前
DeepMimic论文详细解析:基于示例引导的深度强化学习实现物理仿真角色技能
算法·强化学习
我是华为OD~HR~栗栗呀12 小时前
测试转C++开发面经(华为OD)
java·c++·后端·python·华为od·华为·面试
IT成长日记13 小时前
【LVS入门宝典】LVS调度算法轮询(RR)深度解析:从原理到实战的公平调度之道
算法·lvs·rr·轮询调度算法
mldong13 小时前
保姆级教程!手把手教你搭建FastAPI + Vue3前后端分离项目
vue.js·python·全栈