题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1536
题目大意:
首先输入K 表示一个集合的大小 之后输入集合 表示对于一堆石子只能取这个集合中的元素的个数。
之后输入 一个m 表示接下来对于这个集合要进行m次询问
之后m行 每行输入一个n 表示有n个堆 每堆有n1个石子 问这一行所表示的状态是赢还是输 如果赢输入W否则L。
#include <bits/stdc++.h>
#define LL long long
using namespace std;
#define N 10015
//s[]:可以取走的石子个数
//sg[]:0~n的SG函数值
//mk[]:mex{}
int s[10005];
int sg[10005];
int mk[10005];
void getsg(int n)
{
sg[0] = 0;//主要是让终止状态的sg为0
memset(mk, -1, sizeof(mk));
for(int i = 1; i < 10005; i++)
{
for(int j = 0; j < n && s[j] <= i; j++)
mk[sg[i-s[j]]]=i;//将所有后继的sg标记为i,然后找到后继的sg没有出现过的最小正整数
//优化:注意这儿是标记成了i,刚开始标记成了1,这样每次需初始化mk,而标记成i就不需要了
int j = 0;
while(mk[j] == i) j++;
sg[i] = j;
}
}
int main()
{
int n;
while(~scanf("%d",&n),n)
{
for(int i=0;i<n;i++)
{
scanf("%d",&s[i]);
}
sort(s,s+n);//必须排序
getsg(n);
int m;
scanf("%d",&m);
while(m--)
{
int k, a, ans=0;
scanf("%d",&k);
for(int i=0;i<k;i++)
{
scanf("%d",&a);
ans^=sg[a];
}
if(ans)
{
printf("W");
}
else
{
printf("L");
}
}
printf("\n");
}
return 0;
}