- 编程语:C++
- 单个测试集评测时长限制:3秒
题目描述
小明老师最近给学生发布了一道简单的数学题,比如,给出一个区间 K
到 M
,你要求出这个区间内所有数字的数字和之和。所谓的数字和指的是数字每一位相加求和。比如 123
的数字和为 6
。 但由于小明给出的区间很大,所以希望你能给最终的答案 mod(109+7)
。
输入输出格式
输入格式 第一行输入两个整数,K,M
表示区间。 输出格式 一行输出区间数字和 mod(109+7)
。
输入输出样例1
输入 24 69
输出 411
输入输出样例2
输入 70 120
输出 498
说明提示
1≤K,M≤1018
#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring> // 引入字符串处理库
#include<algorithm> // 引入算法库
using namespace std;
#define int long long
const int maxn=1000100; // 定义最大数组大小
const int mod=1e9+7; // 定义模数
int t; // 定义变量t,可能用于存储测试用例数量
int l, r; // 定义变量l和r,用于存储区间的左右边界
int a[maxn], num; // 定义数组a用于存储数字的各个位,num未使用
int f[200][200]; // 定义二维数组f,用于记忆化搜索
int dfs(int x, int sum, bool top) { // 定义深度优先搜索函数dfs
if (!x) return sum; // 如果已经到了最后一位就可以直接返回sum
if (!top && f[x][sum] >= 0) return f[x][sum]; // 最高位是0也直接返回
int bound = top ? a[x] : 9; // 根据top判断枚举的上界bound
int ret = 0;
for (int i = 0; i <= bound; i++) { // 枚举当前数位可能的值
ret = (ret + dfs(x - 1, sum + i, top && i == bound)) % mod;
}
if (!top) f[x][sum] = ret; // 这里对应上面的记忆化,在一定条件下时记录,保证一致性
return ret;
}
int solve(int x) { // 定义解决问题的函数solve
int sum = 0;
while (x) {
a[++sum] = x % 10; // 逆序提取x的每一位放入数组a中
x /= 10;
}
return dfs(sum, 0, 1) % mod; // 从最高位开始枚举
}
signed main() { // 主函数
memset(f, -1, sizeof(f)); // 初始化二维数组f
cin >> l >> r;
cout << (solve(r) - solve(l - 1) + mod) % mod << '\n'; // 计算并输出结果
return 0;
}