http://poj.org/problem?id=2960
/* POJ 2960 S-Nim 大意:有n堆石子,每堆石子个数已知,两人轮流从中取石子, 每次可取的石子数x满足x属于集合S(k) = {s1,s2,s3...sk-1},问先拿者是否有必胜策略? 输入 knum 表示s数组的大小 输入knum个si 表示能一次拿的数量 输入 mnum 表示每次测试数据组数 对于每组 输入lnum表示一共的堆数 之后lnum个数 表示每堆的数量 */ #include<stdio.h> #include<string.h> #include<stdlib.h> #define N 100+10 int knum,mnum,lnum; int ans[N],si[N],hi[N],sg[10010]; int cmp( const void *a , const void *b ) { return *(int *)a - *(int *)b; } int mex(int x)//求x的sg值(可作为模版应用) { int i; if(sg[x]!=-1) return sg[x]; bool vis[N];//注意要讲vis定义到函数里面!因为每次都要改变其值 memset(vis,false,sizeof(vis)); for(i=0;i<knum;i++) { int temp=x-si[i]; if(temp<0) break; sg[temp]=mex(temp); vis[sg[temp]]=true; } for(i=0;;i++) { if(!vis[i]) { sg[x]=i; break; } } return sg[x]; } int main() { int i,j; while(scanf("%d",&knum) && knum) { for(i=0;i<knum;i++) scanf("%d",&si[i]); qsort(si,knum,sizeof(si[0]),cmp); memset(sg,-1,sizeof(sg)); sg[0]=0; memset(ans,0,sizeof(ans)); scanf("%d",&mnum); for(i=0;i<mnum;i++) { scanf("%d",&lnum); for(j=0;j<lnum;j++) { scanf("%d",&hi[i]); ans[i]^=mex(hi[i]);//尼姆博弈 } } for(i=0;i<mnum;i++) { if(ans[i]==0) printf("L"); else printf("W"); } printf("\n"); } return 0; } v
求SG的值的方法 还有一个比较流行的方法是一个DFS的 感觉没有这个速度好