Nim游戏

Nim游戏

基础Nim游戏

公平组合游戏ICG

若一个游戏满足:

  1. 由两名玩家交替行动;
  2. 在游戏进程的任意时刻,可以执行的合法行动与轮到哪名玩家无关;
  3. 不能行动的玩家判负;

则称该游戏为一个公平组合游戏。

NIM博弈属于公平组合游戏,但城建的棋类游戏,比如围棋,就不是公平组合游戏。因为围棋交战双方分别只能落黑子和白子,胜负判定也比较复杂,不满足条件2和条件3。

有向图游戏

给定一个有向无环图,图中有一个唯一的起点,在起点上放有一枚棋子。两名玩家交替地把这枚棋子沿有向边进行移动,每次可以移动一步,无法移动者判负。该游戏被称为有向图游戏。

任何一个公平组合游戏都可以转化为有向图游戏。具体方法是,把每个局面看成图中的一个节点,并且从每个局面向沿着合法行动能够到达的下一个局面连有向边。

NIM游戏

给定 N N N 堆物品,第 i i i 堆物品有 A i A_i Ai 个。两名玩家轮流行动,每次可以任选一堆,取走任意多个物品,可把一堆取光,但不能不取。取走最后一件物品者获胜。两人都采取最优策略,问先手是否必胜。

我们把这种游戏称为 NIM 博弈。把游戏过程中面临的状态称为局面。整局游戏第一个行动的称为先手,第二个行动的称为后手。若在某一局面下无论采取何种行动,都会输掉游戏,则称该局面必败。

所谓采取最优策略是指,若在某一局面下存在某种行动,使得行动后对面面临必败局面,则优先采取该行动。同时,这样的局面被称为必胜。我们讨论的博弈问题一般都只考虑理想情况,即两人均无失误,都采取最优策略行动时游戏的结果。

NIM博弈不存在平局,只有先手必胜和先手必败两种情况。

定理

NIM博弈先手必胜,当且仅当 A 1 ⊕ A 2 ⊕ . . . ⊕ A n ≠ 0 A_1\oplus A_2 \oplus ...\oplus A_n \neq 0 A1A2...An=0 ,反之先手必败。

例子

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

操作步骤:

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

证明

  1. 当每堆石子的个数为 A 1 ⊕ A 2 ⊕ . . . ⊕ A n = x ≠ 0 A_1\oplus A_2 \oplus ...\oplus A_n =x \neq 0 A1A2...An=x=0 时,

x x x 的二进制表示中最高的一位 1 1 1 在第 k k k

a 1 ∼ a n a_1\sim a_n a1an 中必然有一位 a i a_i ai a i a_i ai 的第 k k k 位是 1 1 1

则, a i ⊕ x < a i a_i\oplus x<a_i aix<ai (举例)

那么,从 a i a_i ai 这堆石子中拿走 a i − ( a i ⊕ x ) a_i-(a_i\oplus x) ai(aix) ,第 a i a_i ai 堆石子就会变成 a i − ( a i − ( a i ⊕ x ) ) = a i ⊕ x a_i-(a_i-(a_i\oplus x))=a_i\oplus x ai(ai(aix))=aix

则原石子变为 A 1 ⊕ A 2 ⊕ . . . A i ⊕ x ⊕ . . . ⊕ A n = 0 A_1\oplus A_2 \oplus ...A_i\oplus x\oplus...\oplus A_n =0 A1A2...Aix...An=0

  1. a 1 ⊕ a 2 ⊕ … ⊕ a n = 0 a_1⊕a_2⊕…⊕a_n=0 a1a2an=0,那么无论玩家怎么拿,必然会导致最终异或结果不为 0 0 0

反证法:假设玩家从第 i i i 堆石子拿走若干个,结果仍是 0 0 0 。不妨设还剩下 a ′ a′ a 个,因为不能不拿,所以 0 ≤ a ′ < a i 0≤a′<a_i 0a<ai ,且 a 1 ⊕ a 2 ⊕ … ⊕ a ′ ⊕ … ⊕ a n = 0 a_1⊕a_2⊕…⊕a′⊕…⊕a_n=0 a1a2aan=0

那么, ( a 1 ⊕ a 2 ⊕ … ⊕ a i ⊕ … a n ) ⊕ ( a 1 ⊕ a 2 ⊕ … ⊕ a ′ ⊕ … ⊕ a n ) = a i ⊕ a ′ = 0 (a_1⊕a_2⊕…⊕a_i⊕…a_n)⊕(a_1⊕a_2⊕…⊕a′⊕…⊕a_n)=a_i⊕a′=0 (a1a2aian)(a1a2aan)=aia=0,则 a i = a ′ a_i=a′ ai=a ,与假设 0 ≤ a ′ < a i 0≤a′<a_i 0a<ai 矛盾。

?为什么使用异或

k − N i m k-Nim kNim 游戏

台阶Nim游戏

描述

现在,有一个 n n n 级台阶的楼梯,每级台阶上都有若干个石子,其中第ii级台阶上有 a i a_i ai 个石子 ( i ≥ 1 ) (i≥1) (i1)

两位玩家轮流操作,每次操作可以从任意一级台阶上拿若干个石子放到下一级台阶中(不能不拿)。

已经拿到地面上的石子不能再拿,最后无法进行操作的人视为失败。

问如果两人都采用最优策略,先手是否必胜。

定理

考虑奇数级台阶上的石子

**台阶Nim游戏先手必胜,当且仅当 A 1 ⊕ A 3 ⊕ . . . ⊕ A n ≠ 0 A_1\oplus A_3 \oplus ...\oplus A_n \neq 0 A1A3...An=0 **

证明

先手时,如果奇数台阶异或非0,根据经典Nim游戏,先手总有一种方式使奇数台阶异或为0,于是先手留了技术台阶异或为0的状态给后手

于是轮到后手:

① 当后手移动偶数台阶上的石子时,先手只需将对手移动的石子继续移到下一个台阶,这样奇数台阶的石子相当于没变,于是留给后手的又是奇数台阶异或为 0 的状态

② 当后手移动奇数台阶上的石子时,留给先手的奇数台阶异或非 0 ,根据经典Nim游戏,先手总能找出一种方案使奇数台阶异或为 0

因此无论后手如何移动,先手总能通过操作把奇数异或为0的情况留给后手,当奇数台阶全为 0 时,只留下偶数台阶上有石子。

(核心就是:先手总是把奇数台阶异或为0的状态留给对面,即总是将必败态交给对面)

Sg函数方法

Sg函数方法

集合Nim游戏

Sg函数

Mex运算的定义

S S S 表示一个非负整数集合。定义 m e x ( S ) mex(S) mex(S) 为求出不属于集合 S S S 的最小非负整数的运算,

即: m e x ( S ) = m i n x mex(S) = min{x} mex(S)=minx , x x x 属于自然数,且 x x x 不属于 S S S

人话:找到集合当中不存在的最小自然数

SG函数的定义

在有向图游戏中,对于每个节点(状态) x x x ,设从 x x x 出发共有 k k k 条有向边,分别到达节点 y 1 , y 2 , … , y k y_1, y_2, …, y_k y1,y2,,yk ,定义 S G ( x ) SG(x) SG(x) x x x 的后继节点 y 1 , y 2 , … , y k y_1, y_2, …, y_k y1,y2,,yk S G SG SG 函数值构成的集合再执行 m e x ( S ) mex(S) mex(S) 运算的结果,

即: S G ( x ) = m e x ( { S G ( y 1 ) , S G ( y 2 ) , … , S G ( y k ) } ) SG(x) = mex(\{SG(y_1), SG(y_2), …, SG(y_k)\}) SG(x)=mex({SG(y1),SG(y2),,SG(yk)})

特别地,整个有向图游戏 G G G S G SG SG 函数值被定义为有向图游戏起点 s s s S G SG SG 函数值,即 S G ( G ) = S G ( s ) SG(G) = SG(s) SG(G)=SG(s) S G ( 终 点 ) = 0 SG(终点)=0 SG()=0

形象解释7:00前

性质
  1. SG(i)=k,则i最大能到达的点的SG值为k−1。1.SG(i)=k,则i最大能到达的点的SG值为k−1。
  2. 非0可以走向0
  3. 0只能走向非0
总结

S G ( x ) = 0 SG(x)=0 SG(x)=0 时,说明这个状态走不到终点。

S G ( x ) ≠ 0 SG(x)\neq 0 SG(x)=0 时,说明这个状态的点可以到达终点。

定理

对于 n n n 个图,如果 S G ( G 1 ) ⊕ S G ( G 2 ) ⊕ … S G ( G n ) ≠ 0 SG(G1) \oplus SG(G2) \oplus … SG(Gn)\ne 0 SG(G1)SG(G2)SG(Gn)=0 ,则先手必胜,反之必败

证明(类似于Nim游戏)

① 当 S G ( G i ) = 0 SG(Gi)=0 SG(Gi)=0 时 , x o r = 0 xor=0 xor=0 , 显然先手必败

(PS:结束状态必是状态①,但状态①不一定是结束状态)

② 当 x o r = x ≠ 0 xor=x\ne 0 xor=x=0,因为肯定存在一个 S G ( x i ) ⊕ x < S G ( x i ) SG(xi)\oplus x <SG(xi) SG(xi)x<SG(xi) ,而根据 S G ( ) SG() SG() 的性质1可知, S G ( k ) SG(k) SG(k) 可以走到 0 − k − 1 0−k−1 0k1 的任何一个状态,因此,必定可以从 S G ( x i ) → S G ( x i ) ⊕ x SG(xi)\to SG(xi)\oplus x SG(xi)SG(xi)x , 于是使得 x o r = 0 xor=0 xor=0

③当 x o r = 0 xor=0 xor=0 时,当移动任何一个节点时,对应的SGSG值必然减小,可以证明: x o r ≠ 0 xor\ne 0 xor=0

下证: x o r ≠ 0 xor\ne 0 xor=0

假设: x o r = 0 xor=0 xor=0 ,则说明移动的那个节点的值并没有变化,即从 S G ( k ) SG(k) SG(k) 变成了 k k k,但是这与 S G SG SG 函数的性质1相矛盾,因此不成立

证得:若先手面对的状态是 x o r ≠ 0 xor\ne 0 xor=0 ,则先手方总能使 x o r = 0 xor=0 xor=0 ,即使后手面对的永远是必败态直到结束状态①,因此先手必胜。

Code

893. 集合-Nim游戏 - AcWing题库

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 7, M = N * 2;

int s[N], f[N]; //s存可行的集合 f存所有状态
int n, k;//k是集合中数字的个数,n是石子的堆数

int sg(int x) {
	if(f[x] != -1) return f[x]; //记忆化搜索,如果f[x]已经被计算过,则直接返回

	unordered_set<int> S; //用一个哈希表来存每一个局面能到的所有情况,便于求mex

	for(int i = 1; i <= k; i++) { 
		int sum = s[i];
		if(x >= sum) S.insert(sg(x - sum)); //如果可以减去s[i],则添加到S中
	}

	for(int i = 0;; i++) { //求mex(),找到最小的且不在集合中的数 
		if(!S.count(i)) return f[x] = i;
		// count() 返回匹配给定主键的元素的个数,即count(value)中value出现的次数
	}
}

int main() {
	cin >> k;
	for(int i = 1; i <= k; i++) cin >> s[i];

	memset(f, -1, sizeof f);

	cin >> n;
	int res = 0;
	while(n--) {
		int t;
		cin >> t; //读入每堆石子 
		res ^= sg(t);
	}

	if(res) puts("Yes");
	else puts("No");


	return 0;
}

拆分Nim游戏

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值