NC50615 取石子游戏 2
题目
题目描述
有一种有趣的游戏,玩法如下:
玩家:2人;
道具:N堆石子,每堆石子的数量分别为 ;
规则:
- 游戏双方轮流取石子;
- 每人每次选一堆石子,并从中取走若干颗石子(至少取1颗);
- 所有石子被取完,则游戏结束;
- 如果轮到某人取时已没有石子可取,那此人算负。
假如两个游戏玩家都非常聪明,问谁胜谁负?
输入描述
第一行,一个整数N;
第二行,N个空格间隔的整数 ,表示每一堆石子的颗数。
输出描述
输出仅一行,一个整数,若先手获胜输出win,后手获胜输出lose。
示例1
输入
4 7 12 9 15
输出
win
备注
对于全部数据, 。
题解
知识点:博弈论。
经典的Nim游戏,当所有石子数的异或和为 先手必败,否则必胜。
我们设 时为必败态,否则为必胜态(这里只是假设,字面上的意义还需要证明),考虑证明:
-
游戏终止状态为必败态:
终止状态为全 ,满足我们的假设。
-
必败态只能转到必胜态:
假设存在合法操作使得必败态转到必败态,那么存在一个石子堆被改变了,不妨设它新的数量为 ,设其他没有改变的石子堆的异或和为 ,我们可以得到 ,最后 矛盾。
因此必败态只能转到必胜态。
-
必胜态可以转到必败态:
我们设当前异或和为 ,设 二进制最高位为第 位,那么一定存在一个石子堆的数量二进制第 位为 ,不妨假设这堆石子为 。此时,我们有 ,因为 不会改变 更高位的状态,但会使得 的第 位变为 。那么,我们可以从 中拿出 个石子,此时 ,于是异或和就变为 。
因此必胜态可以转到必败态。
综上,我们证明了我们假设的必胜态和必败态确实是实际意义上的必胜和必败,并且这是一个构造性证明。
时间复杂度
空间复杂度
代码
#include <bits/stdc++.h> using namespace std; using ll = long long; int main() { std::ios::sync_with_stdio(0), cin.tie(0), cout.tie(0); int n; cin >> n; int sum = 0; for (int i = 1;i <= n;i++) { int x; cin >> x; sum ^= x; } cout << (sum ? "win" : "lose") << '\n'; return 0; }
本文来自博客园,作者:空白菌,转载请注明原文链接:https://www.cnblogs.com/BlankYang/p/17661206.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧