SG函数总结

基本概念

首先定义 \(mex\) (minimal excludant)运算,这是施加于一个集合的运算,表示最小的不属于这个集合的非负整数。例如 \(mex\{0,1,2,4\}=3\)\(mex\{2,3,5\}=0\)\(mex\{\}=0\)

对于任意状态 \(x\) ,定义 \(SG(x) = mex(F)\) ,其中 \(F\)\(x\) 后继状态的 \(SG\) 函数值的集合(就是上述 \(mex\) 中的数值)。例如 \(x\) 有三个后继状态分别为 \(SG(a)\)\(SG(b)\)\(SG(c)\) ,那么 \(SG(x) = mex\{SG(a),SG(b),SG(c)\}\) 。当且仅当 \(x\) 为必败点时,\(SG(x)=0\)

游戏和的 \(SG\) 函数等于各个游戏 \(SG\) 函数的 \(Nim\) 和。

取石子问题

\(1\)\(n\) 个石子,每次操作只能取 \(\{ 1, 3, 4\}\) 个石子,先取完石子者胜利,那么各个数的 \(SG\) 值为多少?

初始:\(SG[0] = 0\)\(,f[]=\{1,3,4\}\)

\(x=1\) 时:可以取走 \(1 - f\{1\}\) 个石子,剩余 \(\{0\}\) 个,所以 \(SG[1] = mex\{ SG[0] \}= mex\{0\} = 1\)

\(x=2\) 时:可以取走 \(2 - f\{1\}\) 个石子,剩余 \(\{1\}\) 个,所以 \(SG[2] = mex\{ SG[1] \}= mex\{1\} = 0\)

\(x=3\) 时:可以取走 \(3 - f\{1,3\}\) 个石子,剩余 \(\{2,0\}\) 个,所以 \(SG[3] = mex\{SG[2],SG[0]\} = mex\{0,0\} =1\)

\(x=4\) 时:可以取走 \(4- f\{1,3,4\}\) 个石子,剩余 \(\{3,1,0\}\) 个,所以 \(SG[4] = mex\{SG[3],SG[1],SG[0]\} = mex\{1,1,0\} = 2\)

\(x=5\) 时:可以取走 \(5 - f\{1,3,4\}\) 个石子,剩余 \(\{4,2,1\}\) 个,所以 \(SG[5] = mex\{SG[4],SG[2],SG[1]\} =mex\{2,0,1\} = 3\)

以此类推。

SG函数打表模板

//f[N]:可改变当前状态的方式,N为方式的种类,f[N]要在getSG之前先预处理
//SG[]:0~n的SG函数值
//S[]:为x后继状态的集合
int f[N], SG[maxn], S[maxn];
void  getSG(int n){
    int i, j;
    memset(SG, 0, sizeof(SG));
    //因为SG[0]始终等于0,所以i从1开始
    for(i = 1; i <= n; i++){
        //每一次都要将上一状态 的 后继集合 重置
        memset(S, 0, sizeof(S));
        for(j = 0; f[j] <= i && j <= N; j++)
            S[SG[i-f[j]]] = 1;  //将后继状态的SG函数值进行标记
        for(j = 0; ; j++) if(!S[j]){   //查询当前后继状态SG值中最小的非零值
            SG[i] = j;
            break;
        }
    }
}

posted on 2019-08-23 15:41  solvit  阅读(228)  评论(0编辑  收藏  举报

导航