1 条题解

  • 0
    @ 2025-8-24 23:08:22

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar txy120607
    没有手机痛失绿勾||不怎么上号||正在开发游戏||纯正的yj人||不喜欢玩网游,没错就是084||现在还在脑叶当主管

    搬运于2025-08-24 23:08:22,当前版本为作者最后更新于2025-01-21 14:50:27,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    PS:本人是一个初中的蒟蒻,如有问题,欢迎指出。

    1. 确定算法

    首先,查看算法标签 看一眼要求,一个区间内的符合要求的数,那么就可以判断出用数位 DP。基于前缀和思想,用 [0,R] \left[ 0, R \right] 区间内符合要求的数减去 [0,L1] \left[ 0, L - 1 \right] 区间内符合要求的数得到答案。

    2. 解决难点

    本题最大的难点在数据范围,第一眼过去,1LR101001 \leq L \leq R \leq 10^{100}

    BYD 这破题还要高精。

    但再仔细查看可以看到需要取余,那么直接在计算答案的地方加上取余即可。最难的地方在输入,这里可以用字符串,但别忘了要加一点点代码实现左范围减去一。

    除此之外,由于我们在计算过程中取余,在计算答案时可能会被诡异 BUG 弄得一脸茫然(输出负数),这是因为取余后可能右区间比左区间小,所以最后输出答案时还需要加上取余数再取余。

    最后,使用数位 DP 的板子稍加修改,即可通过。

    附上 AC 代码:

    #include <string>
    #include <iostream>
    
    #define Code using
    #define by namespace 
    #define Txy120607 std;
    
    Code by Txy120607
    
    #define int long long
    const int N = 120, P = 1e9 + 7;  // P 为取余数 
    int num[N]; int f[N][N];
    
    // 初始化 DP 数组
    void init() { 
        for (int i = 0; i <= 9; i++)
            f[1][i] = 1;
        for (int i = 2; i < N; i++) {
            for (int j = 0; j <= 9; j++) {
                for (int k = j; k <= 9; k++) {
                    f[i][j] += f[i - 1][k]; // f[i][j] 计算方式
                }
            }
        }
    }
    
    
    int solve(string e) {
        int cnt = e.size();
        for (int i = cnt - 1; i >= 0; i--) { // 反转字符串
            num[cnt - i] = e[i] - '0';
        }
        int ans = 0, l = 0;
        for (int i = cnt; i >= 1; --i) { // 统计符合条件的数的个数
            int n = num[i];
            for (int j = l; j < n; j++) {
                ans += f[i][j] % P;
                ans %= P;
            }
            if (n < l) break; // 剪枝
            l = n;
            if (i == 1) ans++; // 最后一位的处理
            ans %= P; // 取余
        }
        return ans;
    }
    
    signed main() {
        init();
        string l, r;
        cin >> l >> r;
        
        int i;
        // 实现字符串 l - 1 的效果
        for (i = l.size() - 1; l[i] == '0'; i--); // 从右往左找第一个非零数字
        l[i] -= 1; // 找到的非零数字减去 1
        i++;
        for (; i < l.size(); i++) l[i] = '9'; // 剩余位数都设为 9
    
        // 输出 (r - l + P) % P,保证非负结果
        cout << (solve(r) - solve(l) + P) % P; 
    
        return 0;
    }
    
    • 1

    信息

    ID
    11263
    时间
    1000ms
    内存
    256MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者