• SG函数


    Sprague-Grundy定理(SG定理):

    游戏和的SG函数等于各个游戏SG函数的Nim和。这样就可以将每一个子游戏分而治之,从而简化了问题。而Bouton定理就是Sprague-Grundy定理在Nim游戏中的直接应用,因为单堆的Nim游戏 SG函数满足 SG(x) = x。

    SG函数:

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

    对于任意状态 x , 定义 SG(x) = mex(S),其中 S 是 x 后继状态的SG函数值的集合。如 x 有三个后继状态分别为 SG(a),SG(b),SG(c),那么SG(x) = mex{SG(a),SG(b),SG(c)}。 这样 集合S 的终态必然是空集,所以SG函数的终态为 SG(x) = 0,当且仅当 x 为必败点P时。
     

    解题模型:

    1. 把原游戏分解成多个独立的子游戏,则原游戏的SG函数值是它的所有子游戏的SG函数值的异或。

           即sg(G) = sg(G1) ^ sg(G2) ^ ... ^ sg(Gn)

    2. 分别考虑每一个子游戏,计算其SG值。

    3. 若sg(G)=0,则为P-Position(必败态),否则为N-Position(必胜态)。

    SG值的计算方法:(重点)

    1.可选步数为1~m的连续整数,直接取模即可,SG(x) = x % (m+1);

    2.可选步数为任意步,SG(x) = x;

    3.可选步数为一系列不一定连续的数,用模板计算。

    int F[100];//一系列不一定连续的数,下标从1开始 
     
    inline void BuildF(){
    	
    }
    
    int SG[MAXN];
    bool SGhash[MAXN];
     
    inline int getSG(int x){
    	memset(SGhash,false,sizeof SGhash);
    	for(int j=1 ; j<100 && F[j]<=x ; ++j){
    		SGhash[SG[x-F[j]]] = true;
    	}
    	for(int j=0 ; j<MAXN ; ++j){
    		if(!SGhash[j])return j;
    	}
    	return -1;
    }
    
    inline void BuildSG(int x){
    	memset(SG,0,sizeof SG);
    	for(int i=1 ; i<=x ; ++i){
    		SG[i] = getSG(i);
    	}
    }
  • 相关阅读:
    bzoj3427:[POI2013]BAJ-Bytecomputer
    bzoj3417:[POI2013]MOR-Tales of seafaring
    bzoj1100:[POI2007]对称轴osi
    bzoj3295:[CQOI2011]动态逆序对
    bzoj2286:[SDOI2011]消耗战
    CF1110F Nearest Leaf
    CF1110E Magic Stones
    CF1110D Jongmah
    matlab基础向9:动画
    CF1102D-Balanced Ternary String-(贪心)
  • 原文地址:https://www.cnblogs.com/vocaloid01/p/9513998.html
Copyright © 2020-2023  润新知