题目:题目链接
题意:一串由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; }