题意: 给定一串序列,每次可以删除0右边的数或者把最右边的数改为比他小的数。
开始不会,搜的题解,完全没想到SG函数,哎!
由于题目给定的序列不长,最多就是只有1e6,可以直接暴力打个1~1e6的SG函数值。然后最后只需要根据当前的SGh函数值判断就行。关于这个怎么打SG 函数的表我其实也不太会,反正别人的代码写的挺好,我肯定想不到了。
#include<cstdio>
#include<cstring>
using namespace std;
int sg[1020000];
int get_lenth(int x)
{
if(x<=9) return 1;
else if(x>=10&&x<=99) return 2;
else if(x>=100&&x<=999) return 3;
else if(x>=1000&&x<=9999) return 4;
else if(x>=10000&&x<=99999) return 5;
else return 6;
}
void SG(int n)
{
int len=get_lenth(n);
for(int i=len;i>=1;i--) //每一个位上加上一个数
{
int m=n;
int base=1;
for(int j=1;j<i;j++)
base*=10;
int tmp=m%(base*10)/base;
for(int k=tmp;k<9;k++)
{
m+=base;
sg[m]=1;
}
}
if(len<6) //小于6时末尾加0。
{
int m=n;
int base=1;
for(int i=len;i<6;i++)
{
m*=10;
for(int k=0;k<base;k++)
sg[m+k]=1;
base*=10;
}
}
}
void Init()
{
memset(sg,0,sizeof sg);
sg[0]=1;
for(int i=1;i<1000000;i++)
if(!sg[i]) SG(i);
}
int main()
{
Init();
int n;
char ch[8];
while(scanf("%s",ch)!=EOF)
{
if(ch[0]=='0')
{
puts("Yes");
continue;
}
int len=strlen(ch);
n=0;
for(int i=0;i<len;i++)
{
n*=10;
n+=ch[i]-'0';
}
if(sg[n]) puts("Yes");
else puts("No");
}
return 0;
}