NC50615 取石子游戏 2

题目链接

题目

题目描述

有一种有趣的游戏,玩法如下:
玩家:2人;
道具:N堆石子,每堆石子的数量分别为 X1,X2,...,Xn ​;
规则:

  1. ​ 游戏双方轮流取石子;
  2. ​ 每人每次选一堆石子,并从中取走若干颗石子(至少取1颗);
  3. ​ 所有石子被取完,则游戏结束;
  4. ​ 如果轮到某人取时已没有石子可取,那此人算负。

假如两个游戏玩家都非常聪明,问谁胜谁负?

输入描述

第一行,一个整数N;
第二行,N个空格间隔的整数 Xi ,表示每一堆石子的颗数。

输出描述

输出仅一行,一个整数,若先手获胜输出win,后手获胜输出lose。

示例1

输入

4
7 12 9 15

输出

win

备注

对于全部数据,N5×104,1Xi105

题解

知识点:博弈论。

经典的Nim游戏,当所有石子数的异或和为 0 先手必败,否则必胜。

我们设 i=1nai=0 时为必败态,否则为必胜态(这里只是假设,字面上的意义还需要证明),考虑证明:

  1. 游戏终止状态为必败态:

    终止状态为全 0 ,满足我们的假设。

  2. 必败态只能转到必胜态:

    假设存在合法操作使得必败态转到必败态,那么存在一个石子堆被改变了,不妨设它新的数量为 ai ,设其他没有改变的石子堆的异或和为 sum ,我们可以得到 sumai=sumai=0 ,最后 ai=ai 矛盾。

    因此必败态只能转到必胜态。

  3. 必胜态可以转到必败态:

    我们设当前异或和为 sum ,设 sum 二进制最高位为第 k 位,那么一定存在一个石子堆的数量二进制第 k 位为 1 ,不妨假设这堆石子为 ai 。此时,我们有 aisum<ai ,因为 sum 不会改变 ai 更高位的状态,但会使得 ai 的第 k 位变为 0 。那么,我们可以从 ai 中拿出 ai(aisum) 个石子,此时 aiaisum ,于是异或和就变为 sumsum=0

    因此必胜态可以转到必败态。

综上,我们证明了我们假设的必胜态和必败态确实是实际意义上的必胜和必败,并且这是一个构造性证明。

时间复杂度 O(n)

空间复杂度 O(n)

代码

#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;
}
posted @   空白菌  阅读(54)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
点击右上角即可分享
微信分享提示