AcWing 892. 台阶-Nim游戏
. 台阶-游戏
一、题目描述
现在,有一个 级台阶的楼梯,每级台阶上都有若干个石子,其中第 级台阶上有 个石子()。
两位玩家轮流操作,每次操作可以从任意一级台阶上拿若干个石子放到下一级台阶中(不能不拿)。
已经拿到地面上的石子不能再拿,最后无法进行操作的人视为失败。
问如果两人都采用最优策略,先手是否必胜。
输入格式
第一行包含整数 。
第二行包含 个整数,其中第 个整数表示第 级台阶上的石子数 。
输出格式
如果先手方必胜,则输出 Yes
。
否则,输出 No
。
数据范围
输入样例:
3
2 1 3
输出样例:
Yes
二、结论
如果 奇数 阶台阶的石子个数 异或值不是零,则 先手必胜。
如果 奇数 阶台阶的石子个数 异或值是零, 则 先手必败。

这是一个台阶的初始状态 ,,,, , 只能把大号台阶上的石子往小号台阶上放。
其实台阶经过转换可以变为经典:
把石子从奇数堆移动到偶数堆可以理解为拿走石子,就相当于几个奇数堆的石子在做。
如所给样例, 不为零,所以先手必胜
三、策略
我们可以把每级奇数级台阶上的石子 看做 经典游戏中的每一堆。
然后,我们只需要模拟出经典游戏中的操作:
- 把石子拿掉,就相当于把某奇数级台阶上的若干石子挪到下面的偶数级台阶上
(拿下地面更好,这也是选奇数级不选偶数级的主要原因)
- 如果对手把上面偶数级台阶上的石子挪下来,也没关系,顺水推舟,把它再挪到下一层偶数台阶就行了
四、实现代码
#include <bits/stdc++.h>
using namespace std;
int n, res;
int main() {
cin >> n;
for (int i = 1; i <= n; i++) {
int x;
cin >> x;
if (i % 2) res ^= x;
}
if (res)
puts("Yes");
else
puts("No");
return 0;
}
五、问题与解答
为什么可以这样来转化?
答:假设我们是先手,所给的台阶石子状态的奇数堆做先手能必胜,我就按照能赢的步骤将奇数堆的石子(个)移动到偶数堆(相当于扔掉)。
-
如果对手也是移动奇数堆,我们继续移动奇数堆。
-
如果对手将偶数堆的石子移动到了奇数堆,那么我们紧接着将对手所移动的这么多石子从那个奇数堆移动到下面的偶数堆,两次操作后,相当于偶数堆的石子向下移动了几个,而奇数堆依然是原来的样子,即为必胜的状态。 就算后手一直在移动偶数堆的石子到奇数堆,我们就一直跟着他将石子继续往下移,保持奇数堆不变,如此做下去,我可以跟着后手把偶数堆的石子移动到,然后你就不能移动这些石子了。
所以整个过程,将偶数堆移动到奇数堆不会影响奇数堆做博弈的过程,整个过程可以抽象为奇数堆的博弈。
其他的情况,先手必输的,类似推理,只要判断奇数堆做博弈的情况即可。
为什么只对奇数堆做就可以,而不是偶数堆呢?
答:因为如果是对偶数堆做,对手移动奇数堆的石子到偶数堆,我们跟着移动这些石子到下一个奇数堆,那么最后是对手把这些石子移动到了,我们不能继续跟着移动,就只能去破坏原有的而导致胜负关系的不确定,所以只要对奇数堆做判断即可知道胜负情况。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
2019-10-11 IDEA中css文件包红色下划线
2019-10-11 关于Idea中右边的maven projects窗口找不到了如何调出来
2019-10-11 如何解决IntelliJ idea的maven工程提示的Cannot Resolve Symbol
2018-10-11 LINUX中目录大小查看