poj 2960 S-Nim (SG)
题意:
K个数,s1...sk。
m个状态,对于某一个状态,有L堆石子,每人每次取的石子个数只能是s1...sk的一个,且只能在一堆中取。
输出m个状态是先手胜还是先手败,先手胜输出W,否则输出L。
输入格式及数据范围:
For each test case: The first line contains a number k (0 < k ≤ 100) describing the size of S, followed by k numbers si (0 < si ≤ 10000) describing S. The second line contains a number m (0 < m ≤ 100) describing the number of positions to evaluate. The next m lines each contain a number l (0 < l ≤ 100) describing the number of heaps and l numbers hi (0 ≤ hi ≤ 10000) describing the number of beads in the heaps.
The last test case is followed by a 0 on a line of its own.
思路:
对于每个小堆求sg1...sgL(用记忆搜),则某个状态的SG=sg1^...^sgL。 SG概念题。
代码:
int sg[10005]; int k,m,l; int s[105]; char ss[105]; void dfs(int x){ bool vis[10005] = {0}; if(sg[x]!=-1) return; rep(i,1,k){ if(x>=s[i]){ if(sg[x-s[i]]==-1) dfs(x-s[i]); vis[sg[x-s[i]]] = true; } } for(int i=0;;++i){ if(!vis[i]){ sg[x]=i; return; } } } int main(){ int x; while(scanf("%d",&k),k){ rep(i,1,k) scanf("%d",&s[i]); mem(sg,-1); sg[0]=0; scanf("%d",&m); int geshu=0; while(m--){ scanf("%d",&l); int ans=0; rep(i,1,l){ scanf("%d",&x); if(sg[x]==-1) dfs(x); ans=ans^sg[x]; } if(!ans) ss[++geshu]='L'; else ss[++geshu]='W'; } rep(i,1,geshu) printf("%c",ss[i]); cout<<endl; } }