1 条题解
-
0
自动搬运
来自洛谷,原作者为

txy120607
没有手机痛失绿勾||不怎么上号||正在开发游戏||纯正的yj人||不喜欢玩网游,没错就是084||现在还在脑叶当主管搬运于
2025-08-24 23:08:22,当前版本为作者最后更新于2025-01-21 14:50:27,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
PS:本人是一个初中的蒟蒻,如有问题,欢迎指出。
1. 确定算法
首先,
查看算法标签看一眼要求,一个区间内的符合要求的数,那么就可以判断出用数位 DP。基于前缀和思想,用 区间内符合要求的数减去 区间内符合要求的数得到答案。2. 解决难点
本题最大的难点在数据范围,第一眼过去,。
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
- 上传者