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

news/2025/1/31 18:34:15/

目录

  • 斐波那契博弈(Fibonacci Nim)
  • 齐肯多夫(Zeckendorf)定理
  • 示例分析
  • 实战演练


斐波那契博弈(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} 2n1015

说明

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


题解code:

python">n = int(input())def solve(n):if n == 1:return 1if n == 2:return 2a, 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
如果有更多问题或需要进一步的帮助,可以在评论区留言讨论哦!
如果喜欢的话,请给博主点个关注 谢谢


http://www.ppmy.cn/news/1568211.html

相关文章

开发环境搭建-4:WSL 配置 docker 运行环境

在 WSL 环境中构建&#xff1a;WSL2 (2.3.26.0) Oracle Linux 8.7 官方镜像 基本概念说明 容器技术 利用 Linux 系统的 文件系统&#xff08;UnionFS&#xff09;、命名空间&#xff08;namespace&#xff09;、权限管理&#xff08;cgroup&#xff09;&#xff0c;虚拟出一…

【统计的思想】假设检验(二)

假设检验是根据人为设定的显著水平&#xff0c;对被测对象的总体质量特性进行统计推断的方法。 如果我们通过假设检验否定了零假设&#xff0c;只是说明在设定的显著水平下&#xff0c;零假设成立的概率比较小&#xff0c;并不是说零假设就肯定不成立。如果零假设事实上是成立…

Vue学习四—— Home主体页面

前言 在之前已经实现了登录页面&#xff0c;项目页面增删查改的操作&#xff0c;然后选择项目&#xff0c;进入Home页面&#xff0c;也就是核心主体页面。 一、实现效果图 使用elemrnt-plus的布局容器&#xff0c;将页面分为4部分&#xff0c;也可以选择自己喜欢的布局。 在侧…

无监督学习:聚类、异常检测

聚类 工作原因我对聚类特别熟悉&#xff0c;因此视频课程基本快进看完&#xff0c;不做记录 异常检测 高斯(正态)分布 多特征异常检测 将每个特征作为独立特征&#xff08;实践证明即使不完全独立也影响不大&#xff09;计算高斯分布的参数&#xff0c;然后将待预估样本代入…

LINUX部署微服务项目步骤

项目简介技术栈 主体技术&#xff1a;SpringCloud&#xff0c;SpringBoot&#xff0c;VUE2&#xff0c; 中间件&#xff1a;RabbitMQ、Redis 创建用户 在linux服务器home下创建用户qshh&#xff0c;用于后续本项目需要的环境进行安装配置 #创建用户 useradd 用户名 #设置登录密…

three.js+WebGL踩坑经验合集(2):3D场景被相机裁切后,被裁切的部分依然可以被鼠标碰撞检测得到(射线检测)

three.js内置了Raycaster类实现鼠标的碰撞检测&#xff0c;用它可以实现3D物体的鼠标点击&#xff0c;移入移出&#xff0c;触屏检测一类的业务功能。 该功能虽然强大&#xff0c;但同事们普遍反映不是那么好用&#xff0c;因为它不像其它配套了可视编辑的3D引擎一样&#xff…

新月智能护甲系统CMIA--未来战场的守护者

新月智能护甲系统&#xff08;Crescent Moon Intelligent Armor System&#xff0c;简称CMIA&#xff09; 新月智能护甲系统&#xff08;CMIA&#xff09;是新月结合了她多年的研究成果&#xff0c;开发出的一款高度智能化的个人防护装备。这款护甲集成了先进的环境监测、生命…

机器学习 vs 深度学习

目录 一、机器学习 1、实现原理 2、实施方法 二、深度学习 1、与机器学习的联系与区别 2、神经网络的历史发展 3、神经网络的基本概念 一、机器学习 1、实现原理 训练&#xff08;归纳&#xff09;和预测&#xff08;演绎&#xff09; 归纳: 从具体案例中抽象一般规律…