本题是NIM博弈的一个小小的变形,利用SG函数可以轻松解出
关于SG函数,大家可以参考这篇文章:
http://blog.csdn.net/logic_nut/article/details/4711489
他讲解的很好,但是代码看的时候非常的不舒服,我这边代码都加了详细注释,大家可以拿去参考一下
#include <bits/stdc++.h>
using namespace std;
int n,m;
int sg[1010];//sg列表
bool vis[1010];//能由上个状态到达的状态的标记(mex集合)
void getSG(int len)
{
memset(sg,0,sizeof(sg));
for(int i=1;i<=len;i++)//从1开始遍历到len打sg表
{
memset(vis,false,sizeof(vis));
for(int j=0;i-j-m>=0;j++)//对于每种能到达的情况,添加进mex集合
{
vis[sg[i-j-m]^sg[j]]=true;//此条件在每到题中不同,状态转换
}
for(int j=0;j<=len;j++)//找不在mex中的最小自然数并赋值给sg[i]
{
if(!vis[j])
{
sg[i]=j;
break;
}
}
}
}
int main()
{
std::ios::sync_with_stdio(false);
std::cin.tie(0);
int t;
cin>>t;
for(int cas=1;cas<=t;cas++)
{
cin>>n>>m;
memset(sg,-1,sizeof(sg));
printf("Case #%d: ", cas);
getSG(n-m);
if(n<m||sg[n-m]) printf("abcdxyzk\n");
else printf("aekdycoin\n");
}
return 0;
}