题目
n个珠子
开始是圆排列在一起的
每人只能取m个连续的珠子
不能取的判负
给定n和m,问谁必胜
思路来源
自己一年多前的代码QAQ
题解
现在再补这个题的时候发现不会做了QAQ
温故而知新吖,毕竟那个时候懵懵懂懂抄的题解
然后现在也算是更深入了解Multi-SG这些东西了
先预处理好<=m的情况,
注意长度为n的取了m之后变成n-m一条链,
其充要条件是n>m,
然后先手胜当且仅当对方sg[n-m]先手必败,
区间转移的时候,从中间去掉m,
就是len和i-m-len个段子游戏
如果一点切断可以枚举中间点,一段切断可以枚举左段长
len是可以为0的,0^0=0,不影响答案
然后先手胜还有n==m,考虑全面即可
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=1e3+5;
int t,n,m,sg[maxn];
bool vis[maxn];
void getsg()
{
for(int i=0;i<m;++i)sg[i]=0;
sg[m]=1;
for(int i=m+1;i<=n;++i)
{
memset(vis,0,sizeof vis);
for(int j=0;j<=i-m;++j)
vis[sg[j]^sg[i-m-j]]=1;
for(int j=0;;++j)
if(!vis[j])
{
sg[i]=j;
break;
}
}
}
int main()
{
scanf("%d",&t);
for(int k=1;k<=t;++k)
{
memset(sg,0,sizeof(sg));
scanf("%d%d",&n,&m);
printf("Case #%d: ",k);
getsg();
if((n>m&&!sg[n-m])||n==m)puts("aekdycoin");
else puts("abcdxyzk");
}
return 0;
}