题目传送门

无脑模板,套进去\(AC\)

#include <bits/stdc++.h>

using namespace std;
const int N = 20;

int a[N];    //数位分离的数组
int dp[N][N];//dp[pos][pre]表示当前第pos位,pre是指前一位是什么,这个因素制约了后面的取值个数

/**
 * 功能:统计[0~pos]之间答案
 * @param pos  当前枚举到的数位pos(搜索的深度)由高到低
 * @param pre  前一位是什么
 * @param limit  前几位的数字是否等于上界的前几位数字 op(0/1)(限制本次搜索的数位范围)
 * @return 方案数
 */
int dfs(int pos, int pre, bool limit) {
    //成功到达最后,就是贡献了1个方案
    if (pos == -1) return 1;
    //记忆化搜索,前提是不贴着上界(可以枚举满这一位所有的数字)
    //只有无限制、无前导零才算,不然都是未搜索完的情况
    if (!limit && ~dp[pos][pre]) return dp[pos][pre];
    //up表示能枚举的最高位数
    int res = 0, up = limit ? a[pos] : 9;
    for (int i = pre; i <= up; i++)//尝试填充每一个可能的数字
        res += dfs(pos - 1, i, limit && i == a[pos]);
    //如果不受限制,则记录下来提供下次使用;如果受限制,则一把一利索
    return limit ? res : dp[pos][pre] = res;
}

int calc(int x) {
    //数位分离
    int pos = 0;
    while (x) a[pos++] = x % 10, x /= 10;        //把x按照进制分解到数组中
    return dfs(pos - 1, 0, true);
}

int main() {
    int l, r;
    //初始化
    memset(dp, -1, sizeof dp);
    while (cin >> l >> r)
        printf("%d\n", calc(r) - calc(l - 1));
    return 0;
}

相关文章: