http://acm.hdu.edu.cn/showproblem.php?pid=1536
S-Nim 博弈 需要用SG 处理
最简单的S-Nim博弈是 每一堆可以任取正整数个 比如说 k 可以变成 k-1,k-2,k-3,······0
本题所可以取的数量有了限制 所以要SG处理 把原始数量可以对应到 S-Nim 里面的数量 是多对一的关系
如果原始数量n取过之后可以变成 S-Nim 里面的0,1,2,3,4,····· k-1 而没有 k 的话 那么n就对应到 S-Nim里面的 k
然后就变成最初的S-Nim了
代码:
#include<iostream> #include<cstdio> #include<cstring> #include<string> #include<vector> #include<queue> #include<map> #include<stack> #include<algorithm> using namespace std; //#pragma comment(linker,"/STACK:1000000000,1000000000") #define LL long long const int INF=0x3f3f3f3f; const int N=105; const int M=10005; int choose[N]; int k[M]; int n; int dp(int x) { if(k[x]!=-1) return k[x]; int visited[N]; memset(visited,false,sizeof(visited)); for(int i=0;i<n;++i) { if(x-choose[i]<0) break; visited[dp(x-choose[i])]=true; } for(int i=0;i<=n;++i) if(visited[i]==false) {k[x]=i;break;} return k[x]; } int main() { //freopen("data.txt","r",stdin); while(scanf("%d",&n)!=EOF,n) { for(int i=0;i<n;++i) scanf("%d",&choose[i]); sort(choose,choose+n); memset(k,-1,sizeof(k)); int m; scanf("%d",&m); while(m--) { int l; scanf("%d",&l); int w=0; while(l--) { int tmp; scanf("%d",&tmp); w=(w^dp(tmp)); } if(w) printf("W"); else printf("L"); } printf("\n"); } return 0; }