
点击查看代码
#include<iostream>
using namespace std;
int main()
{
int n;
cin >> n;
int res = 0;
while (n --) {
int x;
scanf("%d", &x);
res ^= x;
}
if (res) puts("Yes");
else puts("No");
return 0;
}
- 先手必胜状态和先手必败状态
① 先手必胜状态:可以走到某一个必败状态;
② 先手必败状态:走不到任何一个必败状态;
- 结论:假设 n 堆石子,石子的数目分别是 a1,a2,⋯,an ,如果 a1⊕a2⊕⋯⊕an≠0 ,则先手必胜,否则,先手必败
① 0⊕0⊕⋯⊕0=0 ,说明没有石子可拿;
② 如果 a1⊕a2⊕⋯⊕an=x≠0 ,那么玩家必然可以通过拿走某一堆里面的若干个石子,使得异或值变为 0
证明:不妨设 x 的二进制表示中,最高位 1 在 x 的第 k 位,那么必然存在一个 ai ,ai 的第 k 位为 1 (反证法:如果 a1,a2,⋯,an 的第 k 位都为 0,则 x 的第 k 位也必然为 0,与最高位 1 在 x 的第 k 位矛盾),ai⊕x<ai,那么从第 i 堆石子中拿走 (ai−ai⊕x) 个石子,第 i 堆石子还剩 ai−(ai−ai⊕x)=ai⊕x ,此时 a1⊕a2⊕⋯⊕an=x⊕x=0
③ 如果 a1⊕a2⊕⋯⊕an=0,那么无论玩家怎么拿,最终的异或值都不为 0
反证法:假设玩家从第 i 堆石子拿走若干个,异或值为 0,不妨设第 i 堆还剩下 a′i 个,0⩽a′i<ai ,a1⊕a2⊕⋯a′i⊕⋯⊕an=0,那么 (a1⊕a2⊕⋯⊕ai⊕⋯⊕an)⊕(a1⊕a2⊕⋯⊕a′i⊕⋯⊕an)=0⊕(ai⊕a′i)=0,推出 ai⊕a′i=0→ai=a′i,与 a′i<ai 矛盾,证明完毕
④ 基于上述结论,当先手遇到的是 a1⊕a2⊕⋯⊕an=x≠0,必然可以通过拿走某一堆里面的若干个石子,使得异或值变为 0,而后手无论怎么拿,最终的异或值都不为 0,不断重复这个过程,后手必然会遇到 0⊕0⊕⋯⊕0=0 这一失败的局面,而当先手遇到的是 a1⊕a2⊕⋯⊕an=0 的局面时,都会给后手创造 a1⊕a2⊕⋯⊕an=x≠0 的局面,先手必败
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!