题意:对一个数字进行两种操作:1、去掉0及其后面的数字;2、将数字的某一位变小,进行最后一步操作的玩家胜出
用sg函数的思想来做,sg = 0表示先手必败状态,那么它的后继状态的sg = 1
用sg函数的思想来做,sg = 0表示先手必败状态,那么它的后继状态的sg = 1
代码如下:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<stack>
#include<queue>
#include<set>
#include<map>
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
#include<time.h>
#include<math.h>
#define N 1000000 + 5
#define inf 0x7fffffff
#define eps 1e-9
#define pi acos(-1.0)
#define P system("pause")
using namespace std;
int sg[N];
int get_length(int n)//求n的位数
{
int k = 0;
while(n)
{
n/=10;
k++;
}
return k;
}
void _extend(int n)
{
int len = get_length(n);
int i;
int base = 1;
for(i = 0; i < len; i++)//将某一位变大得到的数字是必胜状态
{
int m = n;
int temp = (m%(10*base))/base;
m -= temp*base;
for(int j = temp+1;j <= 9; j++)
{
int k = m + j*base;
sg[k] = 1;
}
base*=10;
}
if(len != 6)//在n后面补上0。。。得到的是必胜状态
{
base = 1;
while(get_length(n) != 6)
{
n*=10;
for(i = 0; i < base;i++)
sg[i+n] = 1;
base*=10;
}
}
}
int main()
{
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
int i;
memset(sg,0,sizeof(sg));//sg[i] = 0 状态i是前者必败状态
sg[0] = 1;//这里是前者必胜
for(i = 1 ; i < 1000000; i++)
{
if(!sg[i])
_extend(i);
}
char str[10];
while(scanf("%s",str) != EOF)
{
if(str[0] == '0') {
printf("Yes\n");
continue;
}
int n = 0, i;
for(i = 0; i < strlen(str); i++)
n = n*10 + str[i] - '0';
if(sg[n]) printf("Yes\n");
else printf("No\n");
}
return 0;
}