NIM游戏

【模板】nim 游戏

题目描述

甲,乙两个人玩 nim 取石子游戏。

nim 游戏的规则是这样的:地上有 n 堆石子(每堆石子数量小于 104),每人每次可从任意一堆石子里取出任意多枚石子扔掉,可以取完,不能不取。每次只能从一堆里取。最后没石子可取的人就输了。假如甲是先手,且告诉你这 n 堆石子的数量,他想知道是否存在先手必胜的策略。

输入格式

本题有多组测试数据。

第一行一个整数 TT10),表示有 T 组数据

接下来每两行是一组数据,第一行一个整数 n,表示有 n 堆石子,n104

第二行有 n 个数,表示每一堆石子的数量.

输出格式

T 行,每行表示如果对于这组数据存在先手必胜策略则输出 Yes,否则输出 No

样例 #1

样例输入 #1

2 2 1 1 2 1 0

样例输出 #1

No Yes

结论

如果有 n 堆石子,每堆石子的个数分别为:a1,a2,a3,a4......an,若: a1a2a3a4...an0 则先手必胜,否则先手必输。

操作到最后的时候是 000...0=0

在操作过程中 如果 a1a2a3a4...an0=x 那么我们可以将结果异变成 0

证明

不妨设 x 的二进制最高位 1 在第 k 位,那么 a1,a2,a3,...,an 中,必然有一个数字 aik 位为 1

因为 x 是异或而来的。aix<ai (异或后,第 k 位会变成 0)。

从第 i 堆石子拿走 ai(aix) 个石子,第 i 堆还剩

ai[ai(aix)]

=aiai(aix)

=aix

此时 a1a2a3a4...anx=xx=0

那么这时候通过此项操作,我们可以把操作分为两种情况

1. 如果先手面对的局面是 a1a2a3a4...an0

那么先手总可以通过拿走某一堆若干个石子,将局面变成a1a2a3a4...an=0 后手只能 a1a2a3a4...an0 的情况。

由于游戏一定可以结束,从而到最后的时候先手拿走最后一些石子,留给后手无石子可拿,先手必胜。

2. 如果先手面对的局面是 a1a2a3a4...an=0

那么无论先手怎么拿,都会将局面变成 a1a2a3a4...an0那么后手总可以通过拿走某一堆若干个石子,将局面变成 a1a2a3a4...an=0

如此重复,最后一定是先手面临最终没有石子可拿的状态。先手必败。

#include <cstdio> #include <iostream> using namespace std; int main() { int n; scanf("%d", &n); int res = 0; for (int i = 0; i < n; i++) { int x; scanf("%d", &x); res ^= x; } if (res == 0) puts("No"); else puts("Yes"); return 0; }

__EOF__

本文作者ljfyyds
本文链接https://www.cnblogs.com/ljfyyds/p/17535597.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   ljfyyds  阅读(99)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示