Nim游戏
Nim游戏
给定 堆石子,两位玩家轮流操作,每次操作可以从任意一堆石子中拿走任意数量的石子(可以拿完,但不能不拿),最后无法进行操作的人视为失败。
问如果两人都采用最优策略,先手是否必胜。
输入格式
第一行包含整数 。
第二行包含 个数字,其中第 个数字表示第 堆石子的数量。
输出格式
如果先手方必胜,则输出 Yes 。
否则,输出 No 。
数据范围
,
输入样例:
2 2 3
输出样例:
Yes
解题思路
最基础的博弈论,主要补充证明。
先介绍两种状态,必胜态和必败态,这两种状态都是对于先手而言的。
- 必胜态,即当前状态为先手必胜的状态。在Nim游戏中指的是先手拿完石子后的所有状态中,存在一个状态是必败态。此时由于下一个状态是对手先手必败态,所以当前的状态就是先手必胜态。
- 必败态,即当前状态为先手必败的状态。在Nim游戏中指的是先手拿完石子后的所有状态中,不存在一个状态是必败态(即所有的状态都是对手先手必胜态)。此时由于下一个状态均是对手先手必胜态,所以当前的状态就是先手必败态。
先手必胜状态:可以走到某一个必败状态。先手必败状态:走不到任何一个必败状态。
对于Nim游戏,先给出结论:有堆石子分别为,如果有那么先手必败,否则那么先手必胜。
当每一堆石子均为,即,那么很明显先手必败,此时有。
当,证明一定可以从某一堆中拿走若干个石子使得异或值为。假设的二进制最高位的是第位,因此中必然至少存在一个数,的二进制第位为。因此有,这是因为的结果的第位为,而更高位的数与相同(更高位即大于的高位,的更高位均为,因此异或后的结果与相同),故。然后我们从这堆中拿走个石子,就变成了。剩下的数的异或结果就是
故如果异或值不为那么一定存在一种操作方式使得异或值变成。意味着如果先手遇到异或值不为的状态,那么一定可以转换为让对手先手必败的状态。
如果(其中不全为),那么不管从哪堆石子中拿多少石子,剩下的数的异或值必然不为。反证法,假设从第堆中石子拿完石子后变成了,并且,将该式子与等号两边进行异或,就会得到,即(等号两边同时异或),就矛盾了,因为我们至少要拿一个石子。
因此现在我们得到个结论:
- 没有后继状态的状态是必败状态。
- 对于的状态,一定存在某种移动使得 。
- 对于的状态,一定不存在某种移动使得。
这就说明如果先手时异或值不为,那么一定可以变成异或值为的状态给后手,而后手不管怎么拿都一定会变成异或值不为的状态给先手,重复该过程,可以发现先手总是处于不为的状态而后手总是处于为的状态,由于最终全部石子都会被拿完,且后手的异或值总是为,因此先手必胜而后手必败。
AC代码如下:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int main() { 5 int n; 6 scanf("%d", &n); 7 int ret = 0; 8 while (n--) { 9 int x; 10 scanf("%d", &x); 11 ret ^= x; 12 } 13 printf("%s", ret ? "Yes" : "No"); 14 15 return 0; 16 }
参考资料
AcWing 891. Nim游戏:https://www.acwing.com/video/312/
博弈论 - OI Wiki:https://deploy-preview-980--oi-wiki.netlify.app/math/game-theory/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17125162.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效