题目:题目链接
题意:一串由0~9组成的数字,可以进行两个操作:1、把其中一个数变为比它小的数;2、把其中一个数字0及其右边的
所以数字删除。
两人轮流进行操作,最后把所以数字删除的人获胜,问前者胜还是后者胜。字符串长度为1-6,前者胜输出Yes,否则输
出No.
分析:
1是必败点那么所有被操作成1的数都是必胜点,以此类推由必败点按找游戏的规则反方向推出所有的必胜点
#include <iostream>
#include <cstdio>
#include <string>
#include <string.h>
#include <map>
#include <vector>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <queue>
#include <set>
#include <stack>
#include <functional>
#include <fstream>
#include <sstream>
#include <iomanip>
#include <numeric>
#include <cassert>
#include <bitset>
#include <stack>
#include <ctime>
#include <list>
#define INF 0x7fffffff
#define max3(a,b,c) (max(a,b)>c?max(a,b):c)
#define min3(a,b,c) (min(a,b)<c?min(a,b):c)
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
bool sg[1000000];
int get_length(int n)//得到整数n的位数
{
if(n/100000) return 6;
if(n/10000) return 5;
if(n/1000) return 4;
if(n/100) return 3;
if(n/10) return 2;
return 1;
}
void Deal(int n)
{
int m, i, j, base, len, t;
len = get_length(n);
for(i = 1; i <= len; i++) //对每一位上加上一个数
{
m = n;
base = pow(10,i-1);
t = (m%(base*10))/base;
for(j = t; j < 9; j++)
{
m += base;
sg[m] = true;
}
}
m = n;
base = 1;
for(i = len; i < 6; i++) //后面加0开头的数
{
m *= 10;
for(j = 0; j < base; j++)
sg[m+j] = true;
base *= 10;
}
}
void Init()
{
memset(sg,false,sizeof(sg));
int i;
for(i=1; i<1000000; i++) //由必败点找出所有的必胜点
if(!sg[i])
Deal(i);
}
int main()
{
string s;
int i,sum;
Init();
while(cin>>s)
{
if(s[0]=='0')//0开头的都是必胜的
{
printf("Yes\n");
continue;
}
sum=0;
for(i=0; i<s.size(); i++) //字符串转变成整型
sum=sum*10+s[i]-'0';
if(sg[sum])
printf("Yes\n");
else
printf("No\n");
}
return 0;
}