数位dp做题记录
学习资源:blog
LC2376
Q:求 \([1, n]\) 中,每一位数字无重复的数的个数。
一共只有 \(0\backsim 9\) 共 \(10\) 个数字,用它们的二进制集合作状态表示每一位是否出现过即可。本题需要特别注意前导 \(0\) 不算作出现过的数位,因此需要单独开一维前导 \(0\) 状态,转移时不能将其计入数位。
P2657
经典 \(Windy\) 数。
Q:统计 \([a, b]\) 内不含前导 \(0\) 且任意相邻两个数位上的数字之差至少为 \(2\) 的数的个数。
需要 前导0 \(lead0\) 与 上一位数字 \(last\) 两个状态。
P3413
Q:统计 \([l, r]\) 内包含长度至少为 \(2\) 的回文子串的数的个数。
由回文子串的包含特性,显然只需要看是否包含长度恰好为 \(2\) 或 \(3\) 的回文子串。
- 长度为 \(2\) \(\rightarrow\) 存在某一对相邻位的数字相同
- 长度为 \(2\) \(\rightarrow\) 存在某一对相隔 \(1\) 位的两位数字相同
需要设计 \(limit\),\(lead0\),\(last\),\(last2\),\(lastsame\),\(last2same\) 六种状态 ,其中 \(last2\) 表示当前位的上一位的上一位的数字;\(lastsame\) 表示当前前缀是否存在相邻位相同;\(last2same\) 同理。
LC600
Q:计算在 \([0, n]\) 中有多少个整数的二进制表示中不存在连续的 \(1\)。
二进制上的数位 \(dp\),与十进制没有任何区别。
不需要状态前导0 \(lead0\),因为前导0对答案无影响;在 \(limit, last\) 的基础上,需要额外设计状态 \(exist\),表示是否存在连续 \(1\)。
P6218
Q:计算 \([l, r]\) 所有数满足 二进制中 \(cnt_{0} \geq cnt_{1}\) 的数的个数。
维护 \(lead0\) 和 \(dcnt\),\(dcnt = cnt_{0} - cnt_{1}\)。
P4124
需要设计的状态比较多,但都是一眼。
CF55D
Q:计算 \([l, r]\) 内能被 自身所有位中出现过的所有非 \(0\) 数字整除 的数的个数。
显然我们至少需要设计状态 \(state\),表示数字 \(1\backsim 9\) 是否出现。
为了检验某个数是否能被出现过的数字整除,一个比较暴力的想法:对 \(1\backsim 9\) 每个数字开一维,表示该数 \(\%\) 数字 \(j\) 的余数,但这样设计会导致状态数过于庞大(共 \(9!\) 个)。考虑如何能让状态数降下来,且还能够起检验作用。
由数论知识:一个数 \(x\) 能被某个集合 \(S\) 内的每个数整除,当且仅当 \(x\) 能被 \(S\) 中所有数的 \(lcm\) 整除。那么检验某个数是否能被 \(1\backsim 9\) 中的某个数整除,只需要知道这个数 \(\%\) \(lcm(1\backsim 9)\) 得到的余数是否能被对应数字整除即可。而 \(lcm(1\backsim 9) = 5 \times 7 \times 8 \times 9 = 2520\),显然可以作为数位 \(dp\) 的状态。
CF628D
CF855E
Q:计算 \([l, r]\) 内,满足在 \(b\) 进制下,\(0\backsim b-1\) 均出现偶数次的数的个数。
设计计状态 \(state\),每一位表示对应数字出现次数的奇偶性。
注意这道题是多测,如果对于每一次 \(b,l,r\) 都清空原来计算过的状态,代价显然太高。

浙公网安备 33010602011771号