学习博客:戳这里
解题模型:
1.把原游戏分解成多个独立的子游戏,则原游戏的SG函数值是它的所有子游戏的SG函数值的异或。
即sg(G)=sg(G1)^sg(G2)^...^sg(Gn)。
2.分别考虑没一个子游戏,计算其SG值。
SG值的计算方法:(重点)
1.可选步数为1~m的连续整数,直接取模即可,SG(x) = x % (m+1);
2.可选步数为任意步,SG(x) = x;
3.可选步数为一系列不连续的数,用模板计算。
模板1:打表
1 //f[]:可以取走的石子个数 2 3 //sg[]:0~n的SG函数值 4 5 //hash[]:mex{} 6 7 int f[N],sg[N],hash[N]; 8 9 void getSG(int n) 10 11 { 12 13 int i,j; 14 15 memset(sg,0,sizeof(sg)); 16 17 for(i=1;i<=n;i++) 18 19 { 20 21 memset(hash,0,sizeof(hash)); 22 23 for(j=1;f[j]<=i;j++) 24 25 hash[sg[i-f[j]]]=1; 26 27 for(j=0;j<=n;j++) //求mes{}中未出现的最小的非负整数 28 29 { 30 31 if(hash[j]==0) 32 33 { 34 35 sg[i]=j; 36 37 break; 38 39 } 40 41 } 42 43 } 44 45 }
模板二:DFS
1 //注意 S数组要按从小到大排序 SG函数要初始化为-1 对于每个集合只需初始化1遍 2 3 //n是集合s的大小 S[i]是定义的特殊取法规则的数组 4 5 int s[110],sg[10010],n; 6 7 int SG_dfs(int x) 8 9 { 10 11 int i; 12 13 if(sg[x]!=-1) 14 15 return sg[x]; 16 17 bool vis[110]; 18 19 memset(vis,0,sizeof(vis)); 20 21 for(i=0;i<n;i++) 22 23 { 24 25 if(x>=s[i]) 26 27 { 28 29 SG_dfs(x-s[i]); 30 31 vis[sg[x-s[i]]]=1; 32 33 } 34 35 } 36 37 int e; 38 39 for(i=0;;i++) 40 41 if(!vis[i]) 42 43 { 44 45 e=i; 46 47 break; 48 49 } 50 51 return sg[x]=e; 52 53 }