第一次打关于sg函数的题目,发现是真得有点难,同时运用到dfs和位运算符来表示它后继的状态数
需要注意
sg(i)=mex(sg(i的后继))
mex()集合没出现过的最小自然数
一、sg函数是求一个状态的后继,sg(i)=0,证明这个状态是一个必败态,无论什么操作一定是输
二、如果sg(i)!=0,当前状态必胜,因为可以必然进入后继sg值为零的点所以必胜
三、vis表示是一个上一个状态能到达的标记,把x细分为i和x-m-i两部分,然后对其进行赋值,详细需要自己去理解
,每一题需要自己去积累
#include <iostream>
#include <cstdio>
using namespace std;
int n,m;
int sg[2005];
int dfs(int x)
{
if(x<m)return sg[x]=0;
if(sg[x]!=-1) return sg[x];
bool vis[2005]= {false};
for(int i=0; i<=x-m; i++)
{
vis[dfs(i)^dfs(x-m-i)]=1;
}
for(int i=0;; i++)
{
if(!vis[i])
{
sg[x]=i;
break;
}
}
return sg[x];
}
int main()
{
int t;
cin>>t;
int cou=1;
while(t--)
{
cin>>n>>m;
for(int i=0; i<2000; i++)
sg[i]=-1;
sg[0]=0;
printf("Case #%d: ",cou++);
if(n<m)
{
printf("abcdxyzk\n");
continue;
}
if(dfs(n-m)) printf("abcdxyzk\n");
else
printf("aekdycoin\n");
}
}