E. Segment Sum
E. Segment Sum
You are given two integers and (). Your task is to calculate the sum of numbers from to (including and ) such that each number contains at most different digits, and print this sum modulo .
For example, if then you have to calculate all numbers from to such that each number is formed using only one digit. For the answer is .
Input
The only line of the input contains three integers , and () — the borders of the segment and the maximum number of different digits.
Output
Print one integer — the sum of numbers from to such that each number contains at most different digits, modulo .
Examples
input
10 50 2
output
1230
input
1 2345 10
output
2750685
input
101 154 2
output
2189
Note
For the first example the answer is just the sum of numbers from to which equals to . This example also explained in the problem statement but for .
For the second example the answer is just the sum of numbers from to which equals to .
For the third example the answer is .
解题思路
今天写专门挑了几道数位 dp 的题目来做,选这题来写篇题解吧。
定义 表示前 个数中满足十进制下最多有 个不同数字的数的总和,因此答案就是 。
由于需要知道某个数用了哪些数字,因此必然会用到状态压缩。定义状态 表示满足以下条件的数(用 来表示)的总和:
- 的数位大小为 ,即满足 。
- 若 ,则 ,否则 。
- 若 的最高位是 ,则 ,否则 。
- 由 的二进制下为 的位所对应的数字构成,例如 ,那么 由数字 ,, 构成。
在得到状态转移方程前,还需要再定义状态 表示满足以上相同条件的数(用 来表示)的数量。
当确定了状态 和 后,就可以转移到数位大小为 的状态,根据第 位是哪个数字 来进行状态划分,有状态转移方程
其中 就是 在十进制下的第 位(从右往左,最低位为第 位)。假设 在十进制下有 位, 表示 在二进制下 的个数,那么最终答案就是
AC 代码如下,时间复杂度为 :
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 25, M = 1 << 10, mod = 998244353;
LL l, r;
int m;
int p[N], sz;
int q[N];
int f[N][2][2][M], g[N][2][2][M];
int get(LL x) {
if (!x) return 0;
sz = 0;
while (x) {
p[sz++] = x % 10;
x /= 10;
}
q[0] = 1;
for (int i = 1; i < sz; i++) {
q[i] = q[i - 1] * 10ll % mod;
}
memset(f, 0, sizeof(f));
memset(g, 0, sizeof(g));
g[0][1][0][0] = 1;
for (int i = 0; i < sz; i++) {
for (int j = 0; j <= 1; j++) {
for (int k = 0; k <= 1; k++) {
for (int u = 0; u < M; u++) {
for (int v = 0; v <= 9; v++) {
int &x = f[i + 1][v < p[i] || v == p[i] && j][!v][u | 1 << v];
int &y = g[i + 1][v < p[i] || v == p[i] && j][!v][u | 1 << v];
x = (x + 1ll * v * q[i] * g[i][j][k][u] + f[i][j][k][u]) % mod;
y = (y + g[i][j][k][u]) % mod;
}
}
}
}
}
int ret = 0;
for (int i = 1; i <= sz; i++) {
for (int j = 1; j < M; j++) {
if (__builtin_popcount(j) <= m) {
ret = (ret + f[i][1][0][j]) % mod;
if (i < sz) ret = (ret + f[i][0][0][j]) % mod;
}
}
}
return ret;
}
int main() {
scanf("%lld %lld %d", &l, &r, &m);
printf("%d\n", (get(r) - get(l - 1) + mod) % mod);
return 0;
}
参考资料
Educational Codeforces Round 53 Editorial:https://codeforces.com/blog/entry/62742
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/17788090.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效
2022-10-25 E. FTL