博弈论
公平组合游戏
两人进行公平博弈,只会出现你赢我输,你输我赢两种局面:定义必胜状态为先手必胜的状态,必败状态为先手必败的状态。
有以下三条结论
-
定理 1:没有后继状态的状态是必败状态。
-
定理 2:一个状态是必胜状态当且仅当存在至少一个必败状态为它的后继状态。
-
定理 3:一个状态是必败状态当且仅当它的所有后继状态均为必胜状态。
可以简化为:
-
1:不能操作时即为失败
-
2:一定有一个必胜状态是由必败状态转移的
-
3:一个必败状态一定是由必胜状态转移来,且一定转移为必胜状态
Nim 和
\(n\) 堆物品,每堆有 \(a_i\) 个,两个玩家轮流取走任意一堆的任意个物品,但不能不取。
定义 Nim 和 =\(a_1 \oplus a_2 \oplus \ldots \oplus a_n\)。当且仅当 Nim 和为 0 时,该状态为必败状态;否则该状态为必胜状态。
-
定理 1:没有后继状态的状态是必败状态。
-
定理 2:对于 \(a_1 \oplus a_2 \oplus \ldots \oplus a_n \neq 0\) 的局面,一定存在某种移动使得 \(a_1 \oplus a_2 \oplus \ldots \oplus a_n = 0\)。
-
定理 3:对于 \(a_1 \oplus a_2 \oplus \ldots \oplus a_n = 0\) 的局面,一定不存在某种移动使得 \(a_1 \oplus a_2 \oplus \ldots \oplus a_n = 0\)。
这东西和异或咋扯上关系了呢?
让我们回归一下 \(Nim\) 游戏的最初形式去理解一下:拿石子。
-
1:现在没有石子可以拿了,就输了
-
2:现在局面为必胜状态,我们一定想让对方操作时局面为必败局面,所以会拿石子影响对方局面,使其变成0
-
3:现在局面为必败局面,如果不改变这个局面就败了,所以下一局面必须是必胜局面,不会还是必败局面
现在我们再来看一下理性证明:
-
1,没有后继状态的状态只有一个,即全 0 局面。此时 \(a_1 \oplus a_2 \oplus \ldots \oplus a_n = 0\)。
-
2,不妨假设 \(a_1 \oplus a_2 \oplus \ldots a_n = k \neq 0\)。如果我们要将 \(a_i\) 改为 \(a_i'\),则 \(a_i'=a_i \oplus k\)。假设 \(k\) 的二进制最高位 1 为 \(d\),即 \(2^d \le k < 2^{d + 1}\)。根据异或定义,一定有奇数个 \(a_i\) 的二进制第 d 位为 1。满足这个条件的 \(a_i\) 一定也满足 \(a_i > a_i \oplus k\),因而这也是个合法的移动。(换而言之,这是越异或越小的)
-
3,如果我们要将 \(a_i\) 改为 \(a_i'\),则根据异或运算律可以得出 \(a_i=a_i'\),因而这不是个合法的移动。
SG 函数
\(\operatorname{mex}\) 函数
定义\(\operatorname{mex}\) 函数为不属于集合 S 中的最小非负整数,即:\(\operatorname{mex}(S)=\min\{x\} \quad (x \notin S, x \in N)\)
例如 \(\operatorname{mex}(\{0, 2, 4\})=1,\operatorname{mex}(\{1, 2\})=0。\)
对于状态 \(x\) 和它的所有\(k\) 个后继状态 \(y_1, y_2\), \(\ldots, y_k\),定义 \(\operatorname{SG}\) 函数:\(\operatorname{SG}(x)=\operatorname{mex}\{\operatorname{SG}(y_1), \operatorname{SG}(y_2), \ldots, \operatorname{SG}(y_k)\}\)
\(SG\) 定理
对于由 n 个有向图游戏组成的组合游戏,设它们的起点分别为 \(s_1, s_2, \ldots, s_n\),则有定理:
-
1:有 \(\operatorname{SG}(x)=\operatorname{SG}(s_1) \oplus\operatorname{SG}(s_2) \oplus \ldots \oplus \operatorname{SG}(s_k)\)。
-
2:当且仅当 \(\operatorname{SG}(s_1) \oplus \operatorname{SG}(s_2) \oplus \ldots \oplus \operatorname{SG}(s_n) \neq 0 \)时,这个游戏是先手必胜的。
证明:
-
1:边界:没有出边了,为必败局面
-
2:由 \(\operatorname{mex}\) 定义知 \(a_i\) 可以转移到的局面 \(y\) 的\(\operatorname{SG}(y)\)取遍了[\(0\) - \(\operatorname{SG}(x)-1\)],同时也可能存在\(\operatorname{SG}(y)\) \(>\) \(\operatorname{SG}(a_i)\)的情况,所以这种 \(y\) 能转移到的局面 \(z\) 中一定有\(\operatorname{SG}(z)\)=\(\operatorname{SG}(a_i)\),这相当于 \(a_i\) 没有转移,所以是无用的,有用的部分只会向\(\operatorname{SG}\)函数值更小的地方转移,这等价于 \(Nim\) 游戏取石子,与上面 \(Nim\) 和证明类似
换句话说:\(\operatorname{SG}\) 函数在 \(Nim\) 游戏中等价于 \(Nim\) 和(因为两者都表示当前局面的胜负状态)
\(SG\) 定理适用于任何公平的两人游戏,它常被用于决定游戏的输赢结果。
例题
首先叶子的 \(sg\) 值显然是 \(0\)。对于每个儿子 \(v\),考虑他有什么后继状态。
单独考虑 \(v\) 子树内的博弈,\(sg\) 值是 \(f_v\)。但是由于 \(u,v\) 见有边,我们随时可以割掉这一条边,即 \(v\) 子树游戏中的每个状
态都可以直接通向 \(sg=0\) 的后继状态。那么每个点的 \(sg\) 值都要加 \(1\),也就是 \(v\) 子树的 \(sg\) 值是 \(f_v+1\)。
(实际上也不一定加1,加1只是因为比较简单,加1,2,4,8,16,32,64,128,256...等2的整倍数的数都可,加一个数只是去保障每一
个状态都有直接达到0的方案,这相当于对每个节点的 \(sg\) 值的二进制形式单开一位存这个信息)
点击查看代码
#include<bits/stdc++.h>
const int maxn=2e5+10;
using namespace std;
int t,n,head[maxn],nxt[maxn<<1],to[maxn<<1],tot;
inline void add(int x,int y)
{
to[++tot]=y;
nxt[tot]=head[x];
head[x]=tot;
}
inline int dfs(int x,int fa)
{
int k=0;
for(register int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(y==fa) continue;
k^=dfs(y,x)+1;
}
return k;
}
int main()
{
// freopen("tree2.in","r",stdin);
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>n;
for(register int i=1;i<n;i++)
{
int x,y;
cin>>x>>y;
add(x,y);
add(y,x);
}
cout<<(dfs(1,0)?"Alice":"Bob")<<'\n';
return 0;
}