台阶-Nim游戏
台阶-Nim游戏
现在,有一个 级台阶的楼梯,每级台阶上都有若干个石子,其中第 级台阶上有 个石子。
两位玩家轮流操作,每次操作可以从任意一级台阶上拿若干个石子放到下一级台阶中(不能不拿)。
已经拿到地面上的石子不能再拿,最后无法进行操作的人视为失败。
问如果两人都采用最优策略,先手是否必胜。
输入格式
第一行包含整数 。
第二行包含 个整数,其中第 个整数表示第 级台阶上的石子数 。
输出格式
如果先手方必胜,则输出 Yes 。
否则,输出 No 。
数据范围
,
输入样例:
3 2 1 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 for (int i = 1; i <= n; i++) { 9 int x; 10 scanf("%d", &x); 11 if (i & 1) ret ^= x; 12 } 13 printf("%s", ret ? "Yes" : "No"); 14 15 return 0; 16 }
参考资料
AcWing 892. 台阶-Nim游戏:https://www.acwing.com/video/313/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17127941.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2022-02-16 二分求解最值问题例题