SG函数
Nim游戏
n堆石子 \(a_1\ \ a_2\ \ a_3\ \ a_4\ \ ......\ \ a_n\)
规则(......)
\(a_1\ \ xor\ \ a_2\ \ xor\ \ a_3\ \ xor\ \ a_4\ \ xor\ \ ......\ \ xor\ \ a_n==0\) ? 后手胜 : 先手胜
太简单了? ? ? hhh
上升一下规则
1.每一次可以从第1堆石子取出1或者2或者3颗
2.每一次可以从第2堆石子取出奇数颗
3.每一次可以从第3堆以及后面取出任意颗
求必胜策略
(一脸懵逼......)
不多说了 正式开始
首先我们定义一个DAG
一个入度为零的点作为起点
起点上有一个棋子 先后手沿有向边轮流移动 无法移动者lose
这就基本上把博弈论转换为了抽象模型 ---> 图论 ? ? ?
SG就是在这个DAG上面定义然后&^$@!&#%......
(1)\(mex\)运算
这是一个基于集合的运算
表示 最小 的不属于该集合的 非负整数
例如 \(mex\{0,1,3,5,6,8,9\}=2\)
(2)定义
当前SG函数如下 : \(SG(x)=mex\{SG(y)|y是x的后继\}\)
......只有定义是没有用的
①所有出度为零的点x(我们简称为汇点) \(SG(x)=0\)
②\(SG(x)=0\) 该节点是必败点
必败态:
对于当前状态 TA的后继状态 全部 都是必胜态 那么TA就是必败态
当前状态 无法移动也就是没有后继状态 那么TA就是必败态
如果当前点是一个汇点的话 根据定义 必败无疑
但是如果不是呢 ? ? ?
根据\(mex\)的定义 该节点的后继节点当中所有后继节点 \(SG!=0\)
③\(SG(x)!=0\) 该节点对应状态是必胜状态
那么后继节点中一定存在\(SG=0\)的节点
又回到上面那个\(SG(x)=0\)的问题了
这样会一直递归到x是一个汇点
\(SG(x)=0\) 那么\(TA\)的前驱节点\(SG!=0\) 且是必胜态 那么应该就可以理解了
必胜态:
对于当前状态 TA的后继状态 至少有一个 是必败态 那么TA就是必胜态
必败态:
(1)对于当前状态 TA的后继状态 全部 都是必胜态 那么TA就是必败态
(2)当前状态 无法移动也就是没有后继状态 那么TA就是必败态
\(SG(x)=0\) 对应TA是汇点 或者后继结点\(min\{SG(y)|x\ \ can\ \ go\ \ to\ \ y\}>0\)
恰好对应必败态定义
\(SG(x)!=0\) 对应TA的后继结点 \(0∈\{SG(y)|x\ \ can\ \ go\ \ to\ \ y\}\)
恰好对应必胜态定义
(3)实战
说了定义还是一脸蒙蔽 所以 手玩一下? ? ?
①普通Nim游戏(请使用SG()求解)
n堆石子 \(a_1\ \ a_2\ \ a_3\ \ a_4\ \ ......\ \ a_n\)
对于任意一堆石子\(a_i(1<=i<=n)\)
我们可以取\([1,a_i]\)颗 那么剩余石子的范围就是\([0,a-i-1]\)
\(SG(i)=a_i\)
等一下 我们相当于是把每一个石子堆看成了一个游戏
但是怎么合并呢? ? ?
直接上定理:\(SG_{tot}=SG(1)\ \ xor \ \ SG(2)\ \ xor \ \ SG(3)\ \ xor \ \ SG(4)\ \ xor \ \ ......\ \ xor \ \ SG(n)\)
也就是游戏的SG值就是子游戏的SG值得异或和
然后\(SG_{tot}=0\) 对应必败态 恰好石子堆的异或和为0 就是后手必胜
是不是有些眉目了 ? ? ?
SG定理的证明:【https://www.zhihu.com/question/51290443/answer/125105697】
因为我太菜鸡所以当然不会证明辣
②文艺Nim游戏(请使用SG()求解)
每一次可以从第1堆石子取出1或者2或者3颗
每一次可以从第2堆石子取出奇数颗
每一次可以从第3堆以及后面取出任意颗
其余不变
用SG求解
先埋一个局。。。。。。
SG模板
normal
void calc_SG(int x)
{
for(i ...枚举所有后继状态)
vis[SG[i]]=1;
}
memset(vis,0,sizeof vis);
calc_SG(x);
for(int i=0;;++i) if(!vis[i]) {SG[x]=i;break;}
时间戳优化 (卡常小技巧)
//memset(vis,0,sizeof vis) 会被卡常 所以我们尝试优化
void calc_SG(int x)
{
for(i ...枚举所有后继状态)
vis[SG[i]]=tot;
}
++tot;
calc_SG(x);
for(int i=0;;++i) if(vis[i]!=tot) {SG[x]=i;break;}
例题
我来解上面的局
对于第一种情况 这就是巴什博奕 \(SG[x]=mex\{SG[x-3],SG[x-2],SG[x-1]\}\)
参考博弈树打表也是可以理解的 通式就是\(SG[x]=x%4\)
那么对于第二种情况\(SG[x]=x%2\)
也就是\(SG[x]=mex\{SG[x-1],SG[x-3],......,SG[(x+1)\%2]\}\)
根据博弈树打表也可以理解
第三种情况就是\(Nim\)游戏 可以选择一个一个\(SG\)异或 也可以直接计算\(SG3\)
最终的\(SG_{tot}=SG_1 \bigoplus SG_2 \bigoplus SG_3\)
具体的见例题吧 cdy:别诶