E. Segment Sum

E. Segment Sum

You are given two integers $l$ and $r$ ($l \le r$). Your task is to calculate the sum of numbers from $l$ to $r$ (including $l$ and $r$) such that each number contains at most $k$ different digits, and print this sum modulo $998244353$.

For example, if $k = 1$ then you have to calculate all numbers from $l$ to $r$ such that each number is formed using only one digit. For $l = 10, r = 50$ the answer is $11 + 22 + 33 + 44 = 110$.

Input

The only line of the input contains three integers $l$, $r$ and $k$ ($1 \le l \le r < 10^{18}, 1 \le k \le 10$) — the borders of the segment and the maximum number of different digits.

Output

Print one integer — the sum of numbers from $l$ to $r$ such that each number contains at most $k$ different digits, modulo $998244353$.

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 $l$ to $r$ which equals to $\frac{50 \cdot 51}{2} - \frac{9 \cdot 10}{2} = 1230$. This example also explained in the problem statement but for $k = 1$.

For the second example the answer is just the sum of numbers from $l$ to $r$ which equals to $\frac{2345 \cdot 2346}{2} = 2750685$.

For the third example the answer is $101 + 110 + 111 + 112 + 113 + 114 + 115 + 116 + 117 + 118 + 119 + 121 + 122 + 131 + 133 + 141 + 144 + 151 = 2189$.

 

解题思路

  今天写专门挑了几道数位 dp 的题目来做,选这题来写篇题解吧。

  定义 $dp(N)$ 表示前 $N$ 个数中满足十进制下最多有 $k$ 个不同数字的数的总和,因此答案就是 $dp(r) - dp(l-1)$。

  由于需要知道某个数用了哪些数字,因此必然会用到状态压缩。定义状态 $f(i,j,k,u)$ 表示满足以下条件的数(用 $n$ 来表示)的总和

  • $n$ 的数位大小为 $i$,即满足 $0 \leq n < 10^i$。
  • 若 $n \leq N \bmod 10^i$,则 $j = 1$,否则 $j = 0$。
  • 若 $n$ 的最高位是 $0$,则 $k = 1$,否则 $k = 0$。
  • $n$ 由 $u$ 的二进制下为 $1$ 的位所对应的数字构成,例如 $u = (10011)_2$,那么 $n$ 由数字 $0$,$1$,$4$ 构成。

  在得到状态转移方程前,还需要再定义状态 $g(i,j,k,u)$ 表示满足以上相同条件的数(用 $n$ 来表示)的数量

  当确定了状态 $f(i,j,k,u)$ 和 $g(i,j,k,u)$ 后,就可以转移到数位大小为 $i+1$ 的状态,根据第 $i+1$ 位是哪个数字 $v$ 来进行状态划分,有状态转移方程

$$f(i,j,k,u) + v \cdot 10^i \cdot g(i,j,k,u) \longrightarrow f(i+1, \, [v<p_i \; \text{or} \; v=p_i \; \text{and} \; j], \, [!v], \, u \mid 2^v)$$

$$g(i,j,k,u) \longrightarrow g(i+1, \, [v<p_i \; \text{or} \; v=p_i \; \text{and} \; j], \, [!v], \, u \mid 2^v)$$

  其中 $p_i$ 就是 $N$ 在十进制下的第 $i$ 位(从右往左,最低位为第 $0$ 位)。假设 $N$ 在十进制下有 $sz$ 位,$\text{count}(x)$ 表示 $x$ 在二进制下 $1$ 的个数,那么最终答案就是$$dp(N) = \sum\limits_{i=1}^{sz}{\sum\limits_{j=1}^{2^{10}-1}{[\text{count}(j) \leq m] \cdot f(i,1,0,0)}} \; + \; \sum\limits_{i=1}^{sz - 1}{\sum\limits_{j=1}^{2^{10}-1}{[\text{count}(j) \leq m] \cdot f(i,0,0,0)}}$$

  AC 代码如下,时间复杂度为 $O(2^{10} \cdot \log{N})$:

#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

posted @ 2023-10-25 20:47  onlyblues  阅读(6)  评论(0编辑  收藏  举报
Web Analytics