【总结】数位 DP

记号约定

我们用 \(A=\overline{(a_{n-1} a_{n-2} a_{n-3} \cdots a_{0})_B}\) 表示一个 \(n\)\(B\) 进制数(大多数情况下 \(B=10\)\(B=2\) )。

  • 即: \(A=\overline{(a_{n-1} a_{n-2} a_{n-3} \cdots a_{0})_B}=\sum_{i\in[0,n)} a_i B^i\)

令集合 \(S_B=\{\overline{(a_{n-1} a_{n-2} a_{n-3} \cdots a_{0})_B}|n\in[1,\infty)\cap Z,a_i\in[0,B]\cap Z\}\) 为所有 \(B\) 进制数构成的集合

问题刻画

抽象地来说,一般来说数位 \(\text{DP}\) 要解决的问题都可以转化成下面形式的问题:

定义函数 \(P:S_B\to \{1,0\}\) ,求函数 \(f([l,r])=\sum_{x\in S_B\cap [l,r]} P(x)\)

Acwing 1082. 数字游戏

题目描述

科协里最近很流行数字游戏。

某人命名了一种不降数,这种数字必须满足从左到右各位数字呈非下降关系,如 \(123,446\)

现在大家决定玩一个游戏,指定一个整数闭区间 \([a,b]\),问这个区间内有多少个不降数。

\(1\le a\le b<2^{31}\)

技巧 1 : \(f([l,r])\to S(r) - S(l-1)\)

\(S(i)=\sum_{k\in[st,i]} f([st,k])\)

\(l,r \ge st\) ,那么一定有 \(f([l,r])= S(r) - S(l-1)\)

那么我们可以将问题转化为:

  • 有多少整数 \(v \le \overline{a_{n-1} a_{n-2} a_{n-3} \cdots a_{0}}\) 满足从左到右各位数字呈非下降关系。

技巧 2 : 数位统计的基本集合划分

我们转化的问题为有多少整数 \(v \le \overline{a_{n-1} a_{n-2} a_{n-3} \cdots a_{0}}\) 满足从左到右各位数字呈非下降关系。

对于该问题最棘手的限制其实是对 \(v\) 大小限制(上界)的限制。

为了方便思考我们将所有不带前补 \(0\)\(k < n\)\(B\) 进制数补成带前补 \(0\)\(n\)\(B\) 进制数。

考虑两个带前补 \(0\)\(n\)\(10\) 进制整数:

\(A=\overline{a_{n-1} a_{n-2} a_{n-3} \cdots a_{0}}\)

\(B=\overline{b_{n-1} b_{n-2} b_{n-3} \cdots b_{0}}\)

其中 \(B < A\)

考虑一个位置 \(k\) ,满足 \(\forall i> k,a_i=b_i,a_k>b_k\)

一个直观的标记:

\(A=\overline{a_{n-1} \cdots {\color{red}a_{k}} \cdots a_{0}}\)

\(B=\overline{b_{n-1} \cdots {\color{red}b_{k}} \cdots b_{0}}\)

关于这个位置 \(k\) 有两个显然但十分重要的性质:

  • 对于任意 \(B<A\) 一定存在位置 \(k\)

  • 对于任一 \(k\) 不同的两个数 \(B,C\) 一定有 \(B\not= C\)

那么我们就可以将 \(k\) 作为集合划分的依据,枚举 \(k=k_i\) 时的数的个数。

接下来考虑对于 \(k=k_i\) 时的集合划分情况:

我们考虑 \(k_i\) 位的取值,因为已经第 \(k_i\) 位一定比 \(A\) 小,所以剩下的 \(k_i\) 位可以随便填数。

那么接下来要解决的问题即:

  • 有多少 \(m\) 位十进制数满足 \(A= \overline{a_{m-1} a_{m-2} a_{m-3} \cdots a_{0}}\) 满足从左到右各位数字呈非下降关系。

而对于这个问题我们可以用一个十分简单的 \(\text{DP}\) 解决。

posted @ 2021-10-25 18:49  Themaxmaxmax  阅读(36)  评论(0编辑  收藏  举报