【博弈论】Nim游戏/Nim博弈及其异或的详细易懂理解

  • Nim博弈简介
    • 题面
    • 结论
    • 理解
      • 1.终结状态 和 异或
      • 2.玩家的操作 与 异或
      • 3.如何使用异或
    • 代码
    • 致谢

Nim博弈简介

题面

洛谷P2197

有nnn堆石子(nnn >>> 000),每一堆有aia_iai​(aia_iai​ >>> 000, 111 <=<=<= iii <=<=<= nnn)个石子。
每人每次可以从任意一堆石子里,取出任意多枚石子扔掉,可以取完,不能不取,每次只能从一堆里取。最后没有石子可以取的人输掉这场游戏。
设甲为先手,乙为后手,两个人以最佳策略进行操作。
给出nnn,和这nnn堆石子分别的数量,请问是否存在先手必胜的策略?

结论

如果这n堆石子的数量满足:
a1a_1a1​ xorxorxor a2a_2a2​ xorxorxor a3a_3a3​ xorxorxor ......... xorxorxor ana_nan​ === 000
先手必败,否则先手必胜

理解

要理解结论的式子,就要理解为什么使用异或,以及异或为0的意义。这两点将在接下来的理解中提到。

1.终结状态 和 异或

那么我们首先来看该问题的“终结点”(Terminal Position)是什么。

显然,当游戏结束的时候,场面上的情况为一粒石子都不剩,即:
a1a_1a1​ === a2a_2a2​ === a3a_3a3​ === ......... === ana_nan​ === 000
此时,显然有它们的异或和为0,即:
a1a_1a1​ xorxorxor a2a_2a2​ xorxorxor a3a_3a3​ xorxorxor ......... xorxorxor ana_nan​ === 000

而我们还知道一个特点,对一堆石子aia_iai​操作,将其变为一个数newainewa_inewai​(当然,因为是拿出至少1个石子,所以newainewa_inewai​小于aia_iai​),其实等价于对aia_iai​异或一个数字xxx,来使得aia_iai​ xorxorxor xxx === newaanewa_anewaa​.

因此我们可以得出第一个特性:玩家对某一堆石子的操作实际上等同于对该堆石子的异或。
用人话讲就是,你对aia_iai​操作一次相当于把aia_iai​变成了newainewa_inewai​,只不过可以通过异或运算来达到目的。
就这么简单。

2.玩家的操作 与 异或

然后我们可以看一看玩家的每一次操作对所有石子数量的异或和产生了什么影响。

显然,如果当前状况是
a1a_1a1​ xorxorxor a2a_2a2​ xorxorxor a3a_3a3​ xorxorxor ......... xorxorxor ana_nan​ === 000
那么,上一个状况的时候,一定有异或和不为0,即:
a1a_1a1​ xorxorxor a2a_2a2​ xorxorxor a3a_3a3​ xorxorxor ......... xorxorxor ana_nan​ === kkk(kkk != 0)
原因是,这次操作一定会改变一个数aia_iai​,且只改变aia_iai​。
而现在,aia_iai​与“其他数字的异或和”(注意断句)的异或结果为kkk。如果把“其他数字的异或和”设为xxx,那么现在的aia_iai​与xxx相等。
但是操作之前的aia_iai​与xxx不同,因此他们的异或结果kkk不等于0。
由异或运算的结合律,上一个状况的时候,所有数字的异或结果不为0。

这个时候我们就发现了,既然第1部分中提到,对aia_iai​的操作就是对aia_iai​异或一次,那么根据异或运算的结合律,我们对aia_iai​的一次异或其实就是对总体结果(所有数字的异或和)的一次异或。

OK,那么我们就把整个游戏抽象为了一个异或运算的游戏:
保持原先的规则不变,我们的每次操作都可以让异或和改变,最后不能再操作的人将输掉游戏。
诶,这个时候就有同学要问了:异或和为0不能代表游戏结束啊,也不代表所有数都是0啊。
不着急,你现在一定已经有了一点感觉,但是还有一层窗户纸没有捅破。
下一节我会向各位同学解释如何使用异或和这个东西,并且如何利用异或运算在游戏规则内进行操作。

3.如何使用异或

那么我们假设一个一般的状态:
此时游戏进行到了某个阶段,场上的局面是这样的:
a1a_1a1​ xorxorxor a2a_2a2​ xorxorxor a3a_3a3​ xorxorxor ......... xorxorxor ana_nan​ === kkk
这里的k可没有限制啊,可以等于0的。所以我们分情况讨论。
假设此时我是先手,你是后手。

①k不等于0的情况:

我们知道所有的数字异或的和为kkk,kkk不等于0。设kkk的二进制有iii位,那么显然kkk的最高位即iii位是1。
所以a1a_1a1​到ana_nan​中一定有奇数个数字的第iii位为1(不然k的最高位怎么异或出来的是吧)。
不理解没关系,下面有个例子。
【比如,二进制情况下:11001xor10011=101011001 xor 10011 = 101011001xor10011=1010
1010当中的最高位1就是来自11001的第4位的1,一共有一个数的第4位为1】

理解了这一点,我们就可以想出一个骚操作:你不是异或得到kkk吗,我的目标是让你面对的所有数字都变成0,自然,异或和也就是0了。那么我就要想办法减少你的某一个数字(拿走某一堆中的一些石子)。

所以,怎么减少呢:我们发现,如果让所有数字的异或和再异或它的结果kkk,就可以让它变成0。
而从第2部分中提到的异或的结合律当中,我们可以发现,对异或和异或其实可以用结合律变成对其中的一个数异或。

那么我们要异或谁呢?啊,之前不是提到了那奇数个第iii位(iii是k的位数)为1的数吗,就选你们当中的一个了。
为啥呢,因为异或运算的一个性质,马上就讲。

设aja_jaj​第iii位为1,那么aja_jaj​ xorxorxor kkk === newajnewa_jnewaj​
newajnewa_jnewaj​一定是小于aja_jaj​的,因为kkk的最高位即第iii位也是1。因此对aja_jaj​异或kkk之后,newajnewa_jnewaj​当中高于第iii位的那些数字(即第iii位左侧的那些数字)不会被异或kkk影响到,而第iii位直接变成0,小于第iii位的无论如何变化都不会影响第iii位已经变成0的事实。
也就是newajnewa_jnewaj​的第iii位是0,而aja_jaj​的第iii位是1,且更高位相同,因此newajnewa_jnewaj​一定小于aja_jaj​。
【比如,11000 xor 1111 = 10111,而10111<11000】

很好,异或完毕之后我们就发现这样两件事:
(为了避免影响观看体验,我将xor替换为了^,C++的异或运算符)
a1a_1a1​ ^ a2a_2a2​ ^ a3a_3a3​ ^ ......... ^ ana_nan​ ^ kkk
=== kkk ^ kkk
=== 000
而且
a1a_1a1​ ^ a2a_2a2​ ^ a3a_3a3​ ^ ......... ^ ana_nan​ ^ kkk
=== a1a_1a1​ ^ a2a_2a2​ ^ ......... ^ (aj(a_j(aj​ ^ k)k)k) ^ ......... ^ ana_nan​
=== a1a_1a1​ ^ a2a_2a2​ ^ ......... ^ newajnewa_jnewaj​ ^ ......... ^ ana_nan​
这样,我的异或操作就是符合游戏规则的(因为我确实拿走了一些石子,减少了某一堆石子的个数)

这个时候轮到你了,你的任何操作,无论异或任何的非零正整数,都会使得异或和即a1a_1a1​ ^ a2a_2a2​ ^ a3a_3a3​ ^ ......... ^ ana_nan​的结果从0变成非零的newknewknewk
而我只需要重复上面的操作,只不过把kkk变为newknewknewk,然后重新寻找aja_jaj​而已。因为我们的操作一定是减少有限的石子总数的,而且我面对的永远是a1a_1a1​ ^ a2a_2a2​ ^ a3a_3a3​ ^ ......... ^ ana_nan​不为0的状况,你面对的永远是a1a_1a1​ ^ a2a_2a2​ ^ a3a_3a3​ ^ ......... ^ ana_nan​等于0的状况,所以一定在某次操作之后,你发现的异或和为0的状况是由于所有石子都被我拿完了而导致的,此时你将会输掉游戏。

发现了吗,k不为0的时候我是稳赢的,因为我的每一步都会使得你面对一个a1a_1a1​ ^ a2a_2a2​ ^ a3a_3a3​ ^ ......... ^ ana_nan​等于0的状况,且我们一直在减少石子总量,所以石子总量为0的状况一定出现在你的回合。

而我是先手,所以k不为0时先手必胜。

②k等于0的情况:

风水轮流转,这个时候我发现坏了,我的任何操作都会导致异或和不为0,而你可以用①中的操作不断逼迫我,直到我无路可走。

而我是先手,所以k为0时先手必败。

注:因为题意中提到了:双方,也就是你和我,都是绝顶聪明的,使用最佳策略,所以不存在失误,任何一个先手必胜的情况下都会导致先手必胜的结局。

代码

#include<iostream>
using namespace std;int t;int main()
{cin >> t;while(t--)//t组测试数据{int n, x, k = 0;//初始化异或和k为0,因为任何数异或0都是它本身cin >> n;for(int i = 1; i <= n; ++i)cin >> x, k ^= x;//读入每一堆石子的同时就求出了异或和kcout << (k ? "Yes" : "No") << endl;//如果异或和k不为0则先手必胜,否则先手必败}return 0;
}

致谢

非常感谢各位阅读我的博客,也希望自己的一点拙见能够帮到各位。

转载请标注转自千寒的CSDN博客,谢谢!

【博弈论】Nim游戏/Nim博弈及其异或的详细易懂理解相关推荐

  1. 博弈论石子游戏——nim 游戏

    P2197 [模板]nim 游戏(转自洛谷) 题目描述 甲,乙两个人玩 nim 取石子游戏. nim 游戏的规则是这样的:地上有 n 堆石子(每堆石子数量小于 10^4),每人每次可从任意一堆石子里取 ...

  2. java实现汉诺塔游戏(递归)(附超详细易懂注释)

    我们很容易能想到,可以用递归来实现汉诺塔游戏.因为要将n(n>1)个盘子从"源"柱子移到"目标"柱子,我们要先把n-1个盘子从"源"柱 ...

  3. 博弈论(Nim游戏、有向图游戏之SG函数)

    这里写目录标题 经典NIM游戏 Nim游戏属于公平组合游戏ICG 有向图游戏(SG函数) Mex运算 SG函数 单个有向图(一堆石子) 求SG值(记忆化递归) 有向图游戏的和 ,(多个有向图(多堆石子 ...

  4. 【acm 博弈论 】 之 Nim游戏与sg函数

    文章目录 前言 巴什博弈 威佐夫博弈 Nim游戏 Nim游戏与sg函数 题目 题意 样例 思路 代码 前言 从今天开始复习和整理下acm的部分模块,从博弈论开始. 著名的"取石子" ...

  5. 博弈论与SG函数(Nim游戏)

    博弈论与SG函数(Nim游戏) 目录 博弈论与SG函数(Nim游戏) 游戏状态 状态图(SG图) Nim 游戏 Nim 和 SG函数 Grundy数字 组合博弈游戏 Grundy 游戏 例题 在本篇, ...

  6. 博弈论——关于Nim游戏和SG函数的几个链接

    今天做了一道博弈论的题目,正好去找找相关资料再复习一下. 网上能找到的都是同样的文章,不过我觉得足够了,Nim游戏百度百科里说的很详细,包括公式.证明之类的 http://baike.baidu.co ...

  7. Nim 游戏和 SG 函数

    Nim游戏 Nim游戏定义 Nim游戏是组合游戏(Combinatorial Games)的一种,准确来说,属于"Impartial Combinatorial Games"(以下 ...

  8. 【学习笔记】NIM游戏与SG函数初探

    公平组合游戏ICG 游戏条件介绍: 由两名玩家交替行动 游戏进程的任意时刻,可以执行的合法行动与轮到的玩家无关 若当前玩家无法行动,则判负 则称该组合游戏为公平组合游戏.如NIM游戏等即是经典的公平组 ...

  9. 博弈论(van♂游戏) 笔记

    博客观赏效果更佳 前言 会持续更新的呢,毕竟博弈论是个毒瘤啊. 其实不要以为博弈论很变态,它是很有趣的.能理解透的话,一点都不难.其实,博弈论的本质,就是教你van♂游戏啊! 从一个简单的问题(Nim ...

  10. 【小组专题二:博弈论入门综述(1)】NP状态 | SG函数 | 巴什博奕、威佐夫博弈、斐波那契博弈、Nim游戏、SJ定理

    博弈论综述[1] 前言 博弈与博弈论 博弈树 NP状态 SG函数(Sprague-Grundy) Sprague-Grundy Theorem 巴什博奕 Bash Game 威佐夫博弈 扩展威佐夫博弈 ...

最新文章

  1. skiplist跳表的 实现
  2. 宽度定死、按照行间距、字体算出label高度
  3. CentOS7 下配置 Nginx + PHP7 + MariaDB + ThinkPHP5.1
  4. 社会化分享实现插件,分享到...
  5. 【POJ - 3041】Asteroids (二分图,最小点覆盖)
  6. JavaScript操作大全整理(思维导图七--字符串函数)
  7. 3140: [Hnoi2013]消毒
  8. De 30: Decoupling Linear Systems with Constant Coefficients
  9. Q82:三角形网格[Triangle Mesh]图形的平滑着色[Smooth Shading]
  10. 区块链技术与应用(北大公开课,肖臻)- ETH 反思
  11. 2020全国工业互联网安全技术技能大赛Web题WP
  12. 大数据下的数据分析平台架构
  13. strtoupper() 函数
  14. leetcode每日一题1725. 可以形成最大正方形的矩形数目 哈希表存储 到 贪心遍历 优化~
  15. 优秀的Kafka架构设计
  16. 三天流量有效期具体怎么算_飞猪不从APP提取出来流量有效期多久?如何提取?(含与客服对话)...
  17. 分类中解决类别不平衡问题
  18. 【图像处理】常用色彩空间
  19. C#项目实战|人脸识别考勤
  20. (2018最新)Kali linux 安装中文输入法的方法

热门文章

  1. 权限控制-@Secured注解
  2. javascript之操作文件(Files)
  3. 星际争霸2 AI 开发探索与展望
  4. Geek生活--netHack
  5. Horizontally Visible Segments
  6. iso文件:抱歉,装载文件时出现问题
  7. 四大开源3d游戏引擎探究(前言上)
  8. mysql中like与rlike_Hive中rlike,like,notlike区别及使用
  9. web页面PC端和移动端的区别
  10. 写给理工科人看的乐理(四)和弦与调式