hdu2089 不要62(数位dp入门题)

题目链接: hdu2089 ( 不要62 )

\(dp[i][j]\) 代表 \(i\) 位数首位为 \(j\) 的吉利数字个数。

则有

\[dp[i][j] = \begin{cases}0&,j=4\\ \sum_{k=0}^9 (j\ne 6 \or k\ne 2)dp[i-1][k]&,j\ne 4\end{cases} \]

\([0,n)\) 内吉利数个数时要求

  • 从高位往低位遍历
  • 遍历完当前位后,若高几位出现 \(4\)\(62\) 则停止向低位遍历,跳出循环。

\(AC\) 代码:

/**
 * hdu2089 不要62
 * 数位dp
 */

#include <iostream>
#include <climits>
#include <cmath>
#include <iomanip>
#include <vector>
#include <cstring>
using namespace std;

typedef long long LL;

const int N = 8;
int dp[N][10];  // dp[i][j]代表i位数首位为j时的吉利数字个数

void init()
{
    dp[0][0] = 1;
    for (int i = 1; i < N; ++i) {
        for (int j = 0; j < 10; ++j) {
            if (j != 4)
            for (int k = 0; k < 10; ++k) {
                if(j == 6 && k == 2) continue;
                dp[i][j] += dp[i-1][k];
            }
            // cout << setw(7) << dp[i][j] << ' ';
        }
        // cout << endl;
    }
}

int digit[N];
int solve(int n)  // 求解[0,n)区间内满足条件数字个数
{
    int len = 0;
    while (n) {
        digit[++len] = n % 10;
        n /= 10;
    }
    digit[len+1] = 0;
    int res = 0;
    for (int i = len; i > 0; --i) {
        for (int j = 0; j < digit[i]; ++j) {
            if (j == 2 && digit[i+1] == 6) continue;
            res += dp[i][j];
        }
        if (digit[i] == 4 || digit[i] == 2 && digit[i+1] == 6) break;
    }
    return res;
}

int main()
{
    init();
    int n, m;
    while (cin >> n >> m && (n|m)) {
        cout << solve(m+1) - solve(n) << endl;
    }

    return 0;
}

posted @ 2021-02-04 19:48  Zewbie  阅读(47)  评论(0)    收藏  举报