博弈论做法!!
题面可以简化为,有一堆石子,两个人轮流取紧邻的
然后就很明显的套SG函数做。
注意!!!:
-
枚举要拼凑布条的起点,可以从
。 -
注意要提前预处理,否则每次时间复杂度太高,会爆。
-
每个局面包含的子状态有两种,比如起点枚举到
,若不取则为 ,取了下一段的长度就变为了 ,即另一个子状态,两者异或即为此状态的 值,然后 运算求解。
code:
#include<stdio.h>
#include<string.h>
int p,c,z,n,m;
int sg[1010];
int vis[1010];
void solve(int x)
{
memset(sg,0,sizeof(sg));
for(int i=1;i<=x;i++)
{
memset(vis,0,sizeof(vis));
for(int j=1;j<=i-c+1;j++)
vis[sg[j-1]^sg[i-j-c+1]]=1;
for(int j=1;j<=i-z+1;j++)
vis[sg[j-1]^sg[i-j-z+1]]=1;
for(int j=1;j<=i-n+1;j++)
vis[sg[j-1]^sg[i-j-n+1]]=1;
for(int j=0;;j++)
if(vis[j]==0)
{
sg[i]=j;
break;
}
}
return ;
}
int main()
{
scanf("%d%d%d",&c,&z,&n);
scanf("%d",&m);
solve(1005);
for(int i=1;i<=m;i++)
{
scanf("%d",&p);
int ans=sg[p];
if(ans)
printf("1\n");
else
printf("2\n");
}
return 0;
}