nim 游戏 (博弈论)

若一个游戏满足:

由两名玩家交替行动
在游戏进行的任意时刻,可以执行的合法行动与轮到哪位玩家无关
不能行动的玩家判负
则称该游戏为一个公平组合游戏。

尼姆游戏(NIM)属于公平组合游戏,但常见的棋类游戏,比如围棋就不是公平组合游戏,因为围棋交战双方分别只能落黑子和白子,胜负判定也比较负责,不满足条件2和3。

题目描述
给定nn堆石子,两位玩家轮流操作,每次操作可以从任意一堆石子中拿走任意数量的石子(可以拿完,但不能不拿),最后无法进行操作的人视为失败。
问如果两人都采用最优策略,先手是否必胜。

例如:有两堆石子,第一堆有2个,第二堆有3个,先手必胜。

操作步骤:
1. 先手从第二堆拿走1个,此时第一堆和第二堆数目相同
2. 无论后手怎么拿,先手都在另外一堆石子中取走相同数量的石子即可。

必胜状态和必败状态
在解决这个问题之前,先来了解两个名词:

必胜状态,先手进行某一个操作,留给后手是一个必败状态时,对于先手来说是一个必胜状态。即先手可以走到某一个必败状态。
必败状态,先手无论如何操作,留给后手都是一个必胜状态时,对于先手来说是一个必败状态。即先手走不到任何一个必败状态。
结论
假设nn堆石子,石子数目分别是a1,a2,…,ana1,a2,…,an,如果a1⊕a2⊕…⊕an≠0a1⊕a2⊕…⊕an≠0,先手必胜;否则先手必败。

证明
操作到最后时,每堆石子数都是00,0⊕0⊕…0=00⊕0⊕…0=0
在操作过程中,如果 a1⊕a2⊕…⊕an=x≠0a1⊕a2⊕…⊕an=x≠0。那么玩家必然可以通过拿走某一堆若干个石子将异或结果变为0。
证明:不妨设x的二进制表示中最高一位1在第k位,那么在a1,a2,…,ana1,a2,…,an中,必然有一个数aiai,它的第k为时1,且ai⊕x<aiai⊕x<ai,那么从第ii堆石子中拿走(ai−ai⊕x(ai−ai⊕x)个石子,第ii堆石子还剩ai−(ai−ai⊕x)=ai⊕xai−(ai−ai⊕x)=ai⊕x,此时a1⊕a2⊕…⊕ai⊕x⊕…⊕an=x⊕x=0a1⊕a2⊕…⊕ai⊕x⊕…⊕an=x⊕x=0。
在操作过程中,如果 a1⊕a2⊕…⊕an=0a1⊕a2⊕…⊕an=0,那么无论玩家怎么拿,必然会导致最终异或结果不为00。
反证法:假设玩家从第ii堆石子拿走若干个,结果仍是00。不妨设还剩下a′a′个,因为不能不拿,所以0≤a′<ai0≤a′<ai,且a1⊕a2⊕…⊕a′⊕…⊕an=0a1⊕a2⊕…⊕a′⊕…⊕an=0。那么(a1⊕a2⊕…⊕ai⊕…an)⊕(a1⊕a2⊕…⊕a′⊕…⊕an)=ai⊕a′=0(a1⊕a2⊕…⊕ai⊕…an)⊕(a1⊕a2⊕…⊕a′⊕…⊕an)=ai⊕a′=0,则 ai=a′ai=a′,与假设0≤a′<ai0≤a′<ai矛盾。
基于上述三个证明:
1. 如果先手面对的局面是a1⊕a2⊕…⊕an≠0a1⊕a2⊕…⊕an≠0,那么先手总可以通过拿走某一堆若干个石子,将局面变成a1⊕a2⊕…⊕an=0a1⊕a2⊕…⊕an=0。如此重复,最后一定是后手面临最终没有石子可拿的状态。先手必胜。
2. 如果先手面对的局面是a1⊕a2⊕…⊕an=0a1⊕a2⊕…⊕an=0,那么无论先手怎么拿,都会将局面变成a1⊕a2⊕…⊕an≠0a1⊕a2⊕…⊕an≠0,那么后手总可以通过拿走某一堆若干个石子,将局面变成a1⊕a2⊕…⊕an=0a1⊕a2⊕…⊕an=0。如此重复,最后一定是先手面临最终没有石子可拿的状态。先手必败。

#include<iostream>
#include<cstdio>
using namespace std;

/*
先手必胜状态: 先手操作完, 可以走到一个必败状态
先手必败状态: 先手操作完, 走不到任何一个必败状态
先手必败状态: a1 ^ a2 ^ a3 ^... ^ an = 0;
先手必胜状态: a1 ^ a2 ^ a3 ^... ^ an != 0;
*/

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");
}


 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值