一串石子,每次可以取走若干个连续的石子,取走最后一颗的胜利,给出选取石子数的约束集合,求先手胜负。数据:先给出可取方案的集合,再给去M个K,K表示该串石子的石子数,对于每个K,先手胜利输出1,失败输出2。这题唯一的区别就是取走的石子要有连续,这样每一次取完后,就可以把剩下的省下的看成两串新的取石子游戏,这样就转化成NIM和的问题了。对于每个K求出SG值即可。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
typedef long long ll;
int n,m,k;
int sg[1005];
int s[101];
int x;
int mex(int p)
{
if (sg[p]!=-1) return sg[p];
int t;
bool g[10000];
memset(g,0,sizeof g);
for (int i=0; i<n && s[i]<=p ; i++)
for (int j=0; j+s[i]<=p; j++)
{
t=p-s[i];
t=t-j;
if (sg[t]==-1) sg[t]=mex(t);
if (sg[j]==-1) sg[j]=mex(j);
g[sg[j]^sg[t]]=1;
}
for (int i=0; ; i++)
if (!g[i]) return i;
}
int main()
{
// freopen("in.txt","r",stdin);
while(~scanf("%d",&n))
{
memset(sg,-1,sizeof sg);
for (int i=0; i<n; i++)
{
scanf("%d",&s[i]);
}
sort(s,s+n);
n=unique(s,s+n)-s;
scanf("%d",&m);
for (int i=0; i<m; i++)
{
scanf("%d",&x);
if (sg[x]==-1) sg[x]=mex(x);
if (sg[x]) puts("1");
else puts("2");
}
}
return 0;
}