数位 DP
概述
-
数位 DP 是以从数学意义上的位数出发来 DP 为特点的一类 DP。
-
下述特点中的一部分可能对计数类以外的不适用。
-
状态设计通常包含“考虑到第几位”和“是否已经比上界小”。
-
初始化通常为
或 ,视从高位向低位或从低位向高位而不同。 -
转移的话,除了以位为层之外,没有太多共同点。
-
实现上常常把 DP 的形式拆掉...这让设计的 DP 状态多没面子啊...
-
下面主要分两类来谈。
计数式问题
-
典型代表如
(拆 DP) 和 (不能拆),较为经典的变种有 。 -
特点是其要求往往是“计算
内具有某种性质的数字个数”,且实现思路通常为差分( ,如果因为高精而无法 ,那就把 处加回来),并会记录“是否已经比上界小”。 -
状态通常为
,表示安排完高/低 位,是否已经比上界小,(其他题目要求的性质,),的总方案数。-
所谓“是否已经比上界小”,就是是否在只比较更高位的前提下小于
,这代表着后面可以乱填了。 -
从高位开始的较为常用,因为其转移较为自由,下面以默认从高位开始位前提来谈。
-
-
初始化通常为
。 -
状态转移上,我个人觉得顺推比较舒服。大概就是暴力枚举下一位,计算性质满足情况,然后填表过去。
- 大部分情况下,尝试逆推然后加速转移是不可行的,因为计数式问题的奇怪要求往往导致离散的转移起点。
-
复杂度
,其中 为进制。辅助维开销可能很大,此时不能忽略其复杂度。
P2518 [HAOI2010] 计数
-
题意:给出一个元素为
的可重集 ,求向其任意排列插入任意个 生成的所有数字中有多少个比 小,禁止前导零。保证 也是由这个集合生成的。 -
数据范围:记
为 在十进制下的位数,则 。下面所有题不再给出数据范围,因显然数据范围充分小。 -
设计 DP 如下:
-
状态设计:
表示考虑了高 位,是否已经比 小,还剩 里面的数字可以用的总方案数。- 这里我们把所有生成的
的数字都强行补前导零补到 位,于是变成一个排列问题。
- 这里我们把所有生成的
-
初始化:记
为 的位数, 。 -
状态转移方程:
。不太好形式化,用自然语言说就是选 里面一个数使得生成出的数到目前为止仍然 ,然后转过去。
-
-
然而实际上我并不是这么实现的。考虑设计一个辅助 DP 如下:
-
状态设计:
表示 位与 相同的数的数量。 -
实际上这根本没必要 DP,这东西就是个组合连乘(在剩余的位里面选出
个位置放 ),本质是可重集排列数,即 。
-
-
于是问题变成暴力枚举哪一位开始不一样了,然后直接加对应的
。 -
个人认为舒服得多。奇怪的限制不强的时候,把“已经更小”视为“可以乱搞”然后直接统计方案数是有力的手段。
-
复杂度
,其中 为进制(暴力枚举下一位和求组合的时候都得遍历每个数字)。 -
太大的时候怎么办? -
有一个基于可重集排列和康托展开的
更优解:-
考虑我们和康托展开主要区别是什么:康托展开计算下一位有多少种方式更小,我们则是将这些方式都扩展出来然后统计。
-
那么尝试回到康托展开,总体思路是先认为相等的数码不同,最后除以算重的次数。
-
不妨认为前
位相同,我们计算第 位更小的方案数,以 为例:-
第一位(最高位)更小:
-
填
: 。 -
填
:这是关键!本位上可以从两个 里面选一个,于是是 。 -
填
:相同,考察下一位。注意 此时有两个,所以后面的所有方案乘上 的全局系数!
-
-
第二,...位更小:略。
-
-
最后我们除以
(阶乘顺序按数码从小到大)。 -
回过头来考察,为什么是对的?
-
对于第一位放
:确实是 种。 -
对于第一位放
:后面的方案实际上有 种,这里却除了 。不对吗? -
对的!这里对
除了 ,看似后面只有一个 除多了,但不要忘记“本位上可以从两个 里面选一个”(将对应影响提前算上了)!故实际为 。 -
全局系数也是同样的原理。
-
-
故只需要按下式计算即可:
。-
其中
表示从高到低的第 位上数字, 为因高位相同而产生的全局系数,初始为 。 -
每次算完后,请
。事实上这个 的和大概是用另一个 ta 来维护。 -
之所以看起来和康托展开是反的是因为我们从高位向低位走,康托展开的排列是从前往后考虑。
-
-
于是可以
高效解决。
-
P2657 [SCOI2009] windy 数
-
题意:求
的相邻两位数字之差不超过 的数字个数。 -
设计 DP:
-
状态设计:
表示考虑高 ,是否已经小,结尾为 或未开始(放 )的方案数。 -
初始化:
。。 -
状态转移:
。 的转移相对特殊,不想写了。注意这里的转移是 的。
-
-
其实这个东西也可以拆,就是不是很好拆,需要
这样来。难写程度大概和这个没开始的辅助维是卧龙凤雏。 -
复杂度
,其中 为进制。
P2602 [ZJOI2010] 数字计数
-
题意:求每个数码在
的所有数字中的出现次数之和。 -
设计 DP:这个 DP 不太典型......
- 状态设计:
表示考虑完高 位,是否已经小,末尾是什么的方案数。- 事实上,一旦已经小,我们就立马计数(后面是
),然后后面的容易统计(不行就再拉一个 DP),前面的每个数码加上这个方案数。
- 事实上,一旦已经小,我们就立马计数(后面是
- 状态设计:
-
复杂度
。
P4127 [AHOI2009] 同类分布
-
题意:求
的各位数码之和能整除自身的数的个数。 -
这个的主要难点在于看出应该暴力枚举位和
。然后可以这么 DP:-
状态设计:
表示考虑完高 位,是否已经小,位和离 还差多少,当前 的余数是多少。 -
初始化:
。 -
状态转移:无非还是暴力枚举下一位,然后计算转移到哪。
-
-
复杂度
,状态 ,转移 。
P4317 花神的数论题
-
题意略。
-
暴力枚举有几位是
,然后照旧 表示考虑完高 位,还要放 个 ,是否已经小的方案数。 -
于是变成快速幂。除暴力枚举和二进制外平凡。
?这个 ...有必要吗?把辅助维都算进去了?
CF55D Beautiful numbers
-
题意:求
间可被自身每一位上数字( 除外)整除的数字个数。 -
还是用那一招,暴力枚举。
-
暴力枚举有哪些数字,
然后记录 个余数?-
烦死了拜托,转移写死人。
-
而且这样出来的状态
,转移 ,枚举量 , ,寄了,这还没考虑容斥。
-
-
转而考虑枚举最小公倍数。发现不同的最小公倍数只有
种,上界为 ,于是显然有 的状态, 的转移和 的枚举量。 -
总复杂度
, ,这很 CF。 -
这就完了?不好意思,这个做法得容斥。考虑一个不含
但可以被 整除的数字,它显然会被错误地计算。 -
容斥很烦。考虑再开一维
,其中 为当前各位上的数字的最小公倍数,显然这可以压成 。 -
可是这样复杂度炸了。怎么办?
-
舍弃枚举!把
的取模对象固定为 ,等 DP 结束的时候检查 。 -
那完事了。这个转化确实还挺妙的,枚举的目的是使得状态可以接受,那么没有必要进行不能减小状态的枚举(或者虽然减小但是亏本的枚举)。
P5674 【SWTR-02】Magical Gates
-
题意:求
和 。 -
数据范围:
。 -
这鬼畜的数据范围...读入都是个大问题...不过我们大概率是把它转成二进制处理,先当字符串读进来然后处理成二进制 vector 吧。
-
老规矩,考虑做到
是什么情况然后容斥。唔,显然还是要枚举 来计数,用换底公式可知这玩意也就不到 ,我们后面记 (因为还有第 位),一个方便的办法是不断地拆 lowbit,具体地,每次算 lowbit 长的一段的情况然后递归,复杂度 ,最后求逆元可以忽略不计,中间的 的次幂可以直接预处理(反正也就最多到 ),足够通过本题。 -
p.s.这玩意不讲武德,要求支持高精减一和高精转进制,后者的复杂度是
(这里认为 和 同阶),和瓶颈同阶,故复杂度其实没什么,但写起来非常恶心...算是 push 着我去补高精板子了...那去挑战一下 Super GCD 吧...(第几次了?)(upd:忘了可以单独处理 了...蚌...)
P3413 SAC#1 - 萌数
-
题意略。关键点在于看出任意长回文串都有长为
或 的回文子串,于是问题平凡。 -
本题就是个辅助维地狱:是否开始(准确地说,开始了
个)、是否已经小于、是否回文了、上上个是什么、上个是什么。不过复杂度倒是不高,一个很松的上界是 。 处还是单独处理掉。
位权式问题
-
典型代表如
。 -
位权式问题归在数位 DP 里,真的只能说是沾边。
-
特点是转移式带有某种位权色彩,仿佛逐位地放上去数字一样。
-
没有其他的共性,因为我目前就只找到一道题...所以也就无所谓抽象出共性了...看例题那边吧。
P2647 最大收益
-
题意:有
个物品,每个物品有两个属性 ,选择某个物品可以获得 的收益并使还没有被选的所有物品的 。求最大总收益。 -
数据范围:
。 -
这个东西显然处处透着不对劲,乍一看无后效性似乎是不可能的。
-
想办法找一点性质:时光倒流。我们认为实际上较早选取的物品是较晚决策的,并将所有已经决策的物品的
削减。 -
于是看起来它只有前效性了,我们来设法 DP:
-
状态设计:
表示考虑了前 个物品,选了 个的最大总价值。 -
初始化:
。 -
状态转移方程:
。
-
-
但是这仍然不一定对;也许我们是先选后面的再选前面的。怎么办?
-
不妨假设我们已经决定了选哪些物品。我们来考虑最优的选取顺序是怎样的:一定是先选
大的,后选 小的。 -
那完事了。将物品按
降序排序,然后上去跑上面的 DP。贪心和 DP 的优雅结合。复杂度 。 -
为什么是数位?嗯...我认为那个
是位权,我们是在从低向高地用 填这个数字的每一位。
复杂数位 DP
P7961 [NOIP2021] 数列
-
题意:
-
定义合法序列为满足如下条件的自然数序列
:-
。 -
。
-
-
定义序列
的权值为 。 -
求所有合法序列的权值和,序列是有序序列。
-
-
数据范围:
。 -
这道题乍一看就十分凶险。我们来找一些性质吧。
-
首先,把
的顺序舍弃。顺序唯一的影响是答案统计,这个我们设法用组合数来解决。 -
然后发现限制主要是在
上。于是考虑以 的每一位为核心状态,问题来了,从高向低还是从低向高? -
从低向高!这里我们要处理
的个数,从高向低的做法显然有后效性的,因为进位是有向的。而从低向高考虑的话,低 位一定是确定不变的。 -
那么我们来设法设计
,设计出来就算成功。-
状态设计:
表示-
考虑完
的低 位(认为位权为 的是第 位)。 -
当前
已经决定了 个。 -
当前
,这个只考虑低 位的,更高位不考虑。 -
要对
这位进 。 -
的所有方案的权值和。
-
-
初始化:显然我们没有
可供初始化使用,故考虑直接暴力把 转出来作为初始化。 -
状态转移:
-
暴力枚举在第
位上放多少个 ,即有多少个 等于 ,计算出对应的 来转移。- 转移系数为
,其中 为枚举的多少个 。记得初始化 的 次方。
- 转移系数为
-
-
-
状态数
,转移 ,总复杂度 ,足够通过本题。 -
之所以这里有一个
是因为进位可能进到比 更高的位上。应当注意不能把 往这几位上放。 -
具有一定的计数式问题色彩,但显然不是。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】