1. 程式人生 > >Digital Deletions(博弈)

Digital Deletions(博弈)

Digital deletions is a two-player game. The rule of the game is as following. 

Begin by writing down a string of digits (numbers) that's as long or as short as you like. The digits can be 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 and appear in any combinations that you like. You don't have to use them all. Here is an example: 



On a turn a player may either: 
Change any one of the digits to a value less than the number that it is. (No negative numbers are allowed.) For example, you could change a 5 into a 4, 3, 2, 1, or 0. 
Erase a zero and all the digits to the right of it. 


The player who removes the last digit wins. 


The game that begins with the string of numbers above could proceed like this: 



Now, given a initial string, try to determine can the first player win if the two players play optimally both. 

Input

The input consists of several test cases. For each case, there is a string in one line. 

The length of string will be in the range of [1,6]. The string contains only digit characters. 

Proceed to the end of file. 

Output

Output Yes in a line if the first player can win the game, otherwise output No. 

Sample Input

0
00
1
20

Sample Output

Yes
Yes
No
No

題意:對於一個數,我們有兩種操作:

           ①:改變它的任意一位,使改變後的數小於原數(eg:0,1,2,... ,x)

           ②:刪取任意位置的零,以及它右邊的所有數

問:兩個人輪流玩,第一個人能不能把這個數刪完?

思路:由於兩個人每次都是最優的,且每個人都可以改變任意一個位置的數, 因此,必勝態和必敗態是輪流的。因此我們可以列舉所有必敗態,改變它 的某一位使之成為必勝態,這樣的話我們就可以直接通過標記來獲取結果了。

程式碼如下:

/*
    對於一個數,我們有兩種操作:
       ①:改變它的任意一位,使改變後的數小於原數(eg:0,1,2,... ,x)
       ②:刪取任意位置的零,以及它右邊的所有數
    問:兩個人輪流玩,第一個人能不能把這個數刪完?

    思路:由於兩個人每次都是最優的,且每個人都可以改變任意一個位置的數,
          因此,必勝態和必敗態是輪流的。因此我們可以列舉所有必敗態,改變它
          的某一位使之成為必勝態。
*/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
int book[1000010];
int len(int x)
{
    int ans=0;
    while(x)
    {
        ans++;
        x/=10;
    }
    return ans;
}
void work(int x)
{
    int l=len(x);//求這個數的長度
    for(int i=l; i>=1; i--)//改變每一位的數
    {
        int y=x;
        int pos=1;
        for(int j=1; j<i; j++)//改變第 i 位上的數,因此求pos,用於下面只改變這一位的數
            pos*=10;
        int tmp=(x%(pos*10))/pos;//取x的第 i 位上的數
        for(int j=tmp; j<9; j++)//這個[tmp,9]
        {
            y=y+pos;//只有一位改變
            book[y]=1;//標記必勝態
        }
    }
    if(l!=6)//長度不足6位  後面補零
    {
        int y=x;
        int pos=1;
        for(int i=l; i<6; i++)
        {
            y=y*10;
            for(int j=0; j<pos; j++)//列舉後面的每一個數
                book[y+j]=1;
            pos*=10;
        }
    }
}
int main()
{
    book[0]=1;//0為必勝態
    for(int i=1; i<1000000; i++)//列舉1百萬之內的所有數
        if(!book[i])//必敗態
            work(i);
    char str[10];
    while(~scanf("%s",str))
    {
        if(str[0]=='0')
            printf("Yes\n");
        else
        {
            int sum=0;
            int l=strlen(str);
            for(int i=0; i<l; i++)
                sum=sum*10+str[i]-'0';
            if(book[sum])
                printf("Yes\n");
            else
                printf("No\n");
        }
    }
}