数位dp入门

之前稍微看过一点数位dp, 也没怎么练习, 现在鸽了这么久差不多全忘了.

今天一个小学弟跑来问我一个很水的题

多个输入, 每次一个正整数 n, 问 [1, n] 范围内有多少个回文数

题目没有明说 n 的范围, 我下意识就回顾了一下以前做这种题用的很傻逼的方法

预处理生成范围内所有的回文数, 排序再对每一个输入进行二分, 返回下标

这个做法真的太傻逼了= =
还好看过数位dp, 可以远离这种暴力流.
回顾一下数位dp入门题 hdu2089

不要62

Problem Description
杭州人称那些傻乎乎粘嗒嗒的人为62(音:laoer)。
杭州交通管理局经常会扩充一些的士车牌照,新近出来一个好消息,以后上牌照,不再含有不吉利的数字了,这样一来,就可以消除个别的士司机和乘客的心理障碍,更安全地服务大众。
不吉利的数字为所有含有4或62的号码。例如:
62315 73418 88914
都属于不吉利号码。但是,61152虽然含有6和2,但不是62连号,所以不属于不吉利数字之列。
你的任务是,对于每次给出的一个牌照区间号,推断出交管局今次又要实际上给多少辆新的士车上牌照了。

Input

输入的都是整数对n、m(0

Output

对于每个整数对,输出一个不含有不吉利数字的统计个数,该数值占一行位置。

Sample Input

1 100
0 0

Sample Output

80

当时照着模板打的代码

#include 
#include 
#include 

using namespace std;

long long DDP[20][2];
int TN[20];

long long DigtialDFS(int pos, int pre, int sta, bool lead, bool limit){
    if(pos == -1) return 1;
    if(!lead && !limit && DDP[pos][sta] != -1) return DDP[pos][sta];
    int up = limit ? TN[pos] : 9;
    long long res = 0;
    for(int i = 0; i <= up; i++){
        if(i == 4 || (pre == 6 && i == 2)) continue;
        res += DigtialDFS(pos - 1, i, i == 6, lead && i == 0, limit && i == TN[pos]);
    }
    if(!limit) DDP[pos][sta] = res;
    return res;
}

long long DigtialDP(int x){
    int pos = 0;
    while(x) TN[pos++] = x % 10, x /= 10;
    return DigtialDFS(pos - 1, -1, 0, true, true);
}

int main()
{
    int n, m;

    memset(DDP, -1LL, sizeof(DDP));
    while(scanf("%d%d", &n, &m) != EOF && (n || m)) printf("%I64d\n", DigtialDP(m) - DigtialDP(n - 1));
    return 0;
}

一会儿再补注释和思路

#include 
#include 

int DDP[9][9][2];
int TN[20];

int DigtialDFS(int len, int pos, int sta, int limit){
    int i, up, res = 0;
    if(pos == -1) return sta;
    if(!limit && DDP[len][pos][sta] != -1) return DDP[len][pos][sta];
    up = limit ? TN[pos] : 9;
    for(i = 0; i <= up; i++){
        if(pos == len && i == 0) res += DigtialDFS(len - 1, pos - 1, sta, limit && i == up);
        else if(sta && pos < (len + 1) / 2) res += DigtialDFS(len, pos - 1, i == TN[len - pos], limit && i == up);
        else res += DigtialDFS(len, pos - 1, sta, limit && i == up);
    }
    if(!limit) DDP[len][pos][sta] = res;
    return res;
}

int DigtialDP(int x){
    int pos = 0;
    while(x) TN[pos++] = x % 10, x /= 10;
    return DigtialDFS(pos - 1, pos - 1, 1, 1);
}

int main()
{
    int n;

    memset(DDP, -1, sizeof(DDP));
    while(scanf("%d", &n) != EOF && n) printf("%d\n", DigtialDP(n) - 1);
    return 0;
}

你可能感兴趣的:(数位dp入门)