Hdu 1404 Digital Deletions

Problem地址:http://acm.hdu.edu.cn/showproblem.php?pid=1404

刚开始想采取找规律的方法解题,可以没有发现规律。无奈,只好采用求PN点的方法。

我们假设数字最右边为第一位,且为最低位。那么可以知道当最高位为0时,那么先手的人必定能胜利,这个可以作为一个剪枝条件。

接下来就是两种操作了:1.降低其中任何一位

             2.把其中一个0及这位0后面所有的数字删去

我们只需通过这两个操作,寻找目标数字的后续数字状态的PN状态,即可求得目标数字的PN状态。其实我们只需判断后续状态中有没有P点就行了,如果有P点,那么目标数字的状态为N点。如果没有N点,那么目标数字的状态为P点。通过这方法,就可以求得题目要求数字的PN状态了。

#include <iostream>
#include <cstring>
#include <sstream>
#include <cstdio>

using namespace std;

const int MAXN = 1000000 + 5;
int sg[MAXN];

stringstream ss;
int length ;

inline int Get_digit( int num, int i ) // 求出数字第i位数,最右边为第1位
{
    switch (i){
        case 1: return num%10;
        case 2: return num%100/10;
        case 3: return num%1000/100;
        case 4: return num%10000/1000;
        case 5: return num%100000/10000;
        default : return num/100000;
    };
}

int Get_sg( int num ) // 求sg值
{
    if( sg[num]!=-1 )
        return sg[num];
    int temp = 1;
    int orignal = num;
    int i;
    for( i=0;i<length-1;i++ ) // 缩小第i位的值
    {
        num = orignal;
        if( Get_digit( num, i+1 )==0 )
        {  // 消去0即后面所有的数
            if( Get_sg( num/( temp*10 ) )==0 ) // 发现必败点
            {
                sg[ orignal ] = 1;  // 则此点为必胜点
                return 1;
            }
        }
        num = orignal;
        while( Get_digit( num, i+1)!=0 )
        {
            num = num - temp;
            if( Get_sg( num )==0 ) // 发现必败点
            {
                sg[ orignal ] = 1; // 则此点为必胜点
                return 1;
            }
        }
        temp = temp * 10;
    }

    num = orignal;
    while( Get_digit(num, length)>1 ) // 最高位单独处理
    {     // 避免出现 类似于  123 -> 23 的情况
            num = num - temp;
            if( Get_sg( num )==0 ) // 发现必败点
            {
                sg[ orignal ] = 1; // 则此点为必胜点
                return 1;
            }
    }
    sg[orignal] = 0; // 没有发现必败点,则此点即为必败点
    return 0;
}

int main()
{
    memset( sg, -1,sizeof(sg) );  // 初始化
    char in[10];
    int num, ans;
    sg[0] = 1;
    sg[1] = 0;  // 初始化
    while( scanf("%s", in)!=EOF )
    {
        if( in[0]=='0' ) // 最高为为0, 则一定胜利
        {
            printf( "Yes
" );
            continue;
        }
        ss.clear();
        ss << in;
        ss >> num; // char转int
        length = strlen(in);  // 求该数字的长度
        ans = Get_sg( num );
        if( ans )
        {
            printf( "Yes
" );
        }
        else
        {
            printf( "No
" );
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Emerald/p/4065394.html