题意:给一个六位数,两个人轮流修改这个六位数,你可以将其中的一位改成比他小的任何一个数,当这位为0的时候他的右边就可以删除掉,最后一个把这个六位数删除的为赢家。
思路:我们定义一个数组sg[]来存储这个数是否是必胜点,如果为必胜点为1,必败点为0.
由题意我们可以知道,1这个点为必败点,那么可以到达1这个点的都是必胜点,可以到达1的有2,3,4,5,6,7,8,9 还有10**** 星号代表任何数。
其实能达到每个必败点的必胜点都是由着两部分组成的 所以我们可以把每个必胜点表示出来,然后看读入的这个点是不是必胜点就可以了。
下面看代码 许多东西我在代码中写出来了。可以看看
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<iostream>
using namespace std;
#define MAXN 1000000
int sg[MAXN];
int length_len(int y) //计算n的长度函数
{
if(y / 100000)return 6;
if(y / 10000)return 5;
if(y / 1000)return 4;
if(y / 100)return 3;
if(y / 10)return 2;
return 1;
}
void solve(int n) //找出能转换成n的点 那么这些点一定为必胜点 因为n是必败点
{
int len = length_len(n);
int i;
for(int i = len;i >= 1;i--) //在这个位加个数然后让他们的sg为1
{
int m = n;
int base = 1;
for(int j = 1;j < i;j++) //这个base的作用就是要在每一位上加上去的数
{
base = base * 10;
}
int tem = (m % (base * 10)) / base;//作用就是求要加的这个位是几然后就是几重循环
for(int j = tem;j < 9;j++)
{
m = m + base;
sg[m] = 1;
}
}
if(len!=6) //这个地方就是在这个数后面添上一个0然后0后面可以是任何数10****星号代表任何数
{
int m = n;
int base = 1;
for(int i = len;i < 6;i++)
{
m = m * 10;
for(int b = 0;b < base;b++)
{
sg[m + b] = 1;
}
base*=10;
}
}
}
void fun(int x)
{
memset(sg,0,sizeof(sg));//这个地方坑死了
sg[0] = 1;
int i; //这个一定不能少的
for(i = 1;i < x;i++)
{
if(!sg[i])
solve(i);
}
//printf("%d = i",i);
}
int main()
{
fun(MAXN); //这个地方也能写错真是够了
char s[8];
while(~scanf("%s",s))
{
if(s[0] == '0')
{
printf("Yes\n");
continue;
}
int sum = 0;
int len = strlen(s);
for(int i = 0;i < len;i++)
{
sum = sum * 10;
sum = sum + s[i] - '0';
}
//printf("%d *",sum);
if(sg[sum] == 0)
printf("No\n");
else
printf("Yes\n");
// printf("%d",sum);
}
return 0;
}