SG 函数学习

\(Mex\) 运算

\(mex(S)\) 为不属于集合 \(S\) 的最小非负整数,即:

\[mex(S)=\min \limits_{x \in \mathbb{N},x \not\in S} \{x\} \]

eg:\(mex(\{1,2,4,5\})=3,mex(\{\})=0\)

有向图游戏

有向无环图中,一颗棋子放在起点,双方轮流将这枚棋子沿有向边移动,不能移动则输

博弈论问题可转化为有向图游戏

\(SG\) 函数

在有向图游戏中,定义 \(SG(x)\)\(x\) 节点的后继节点 \(y_1,y_2,...,y_n\) 的 SG 值组成的集合的 Mex,即:

\[SG(x)=mex(\{SG(y_1),SG(y_2),...,SG(y_n)\}) \]

一个有向图游戏 \(G\) 的 SG 值为起点的 SG 值

SG 定理

由 n 个有向图游戏组成的游戏的 SG 值为所有子游戏 \(G_1,G_2,...,G_n\) 的 SG 值的异或值,即

\[SG(G)=SG(G_1) \ xor \ SG(G_2) \ xor \ ... \ xor \ SG(G_n) \]

例题

hdu1847

SG 函数模板

/************************************************
*Author        :  lrj124
*Created Time  :  2020.08.14.10:38
*Mail          :  1584634848@qq.com
*Problem       :  hdu1847
************************************************/
#include <cstring>
#include <cstdio>
const int maxn = 1000 + 10;
int f[maxn],sg[maxn];
bool vis[maxn];
inline void get_sg() {
	for (int i = 1;i < maxn;i++) {
		memset(vis,false,sizeof vis);
		for (int j = 1;j <= f[0] && i-f[j] >= 0;j++) vis[sg[i-f[j]]] = true;
		for (int j = 0;;j++) if (!vis[j]) { sg[i] = j; break;}
	}
}
int main() {
	freopen("hdu1847.in","r",stdin);
	freopen("hdu1847.out","w",stdout);
	for (int i = 1;i < maxn;i <<= 1) f[++f[0]] = i;
	get_sg();
	for (int n;scanf("%d",&n) ^ EOF;puts(sg[n] ? "Kiki" : "Cici"));
	return 0;
}
posted @ 2020-08-14 11:29  lrj124  阅读(248)  评论(0编辑  收藏  举报