加载中...

数位dp做题记录

学习资源:blog

LC2376

Q:求 \([1, n]\) 中,每一位数字无重复的数的个数。

一共只有 \(0\backsim 9\)\(10\) 个数字,用它们的二进制集合作状态表示每一位是否出现过即可。本题需要特别注意前导 \(0\) 不算作出现过的数位,因此需要单独开一维前导 \(0\) 状态,转移时不能将其计入数位。

P2657

经典 \(Windy\) 数。

Q:统计 \([a, b]\) 内不含前导 \(0\) 且任意相邻两个数位上的数字之差至少为 \(2\) 的数的个数。

需要 前导0 \(lead0\)上一位数字 \(last\) 两个状态。

code

P3413

Q:统计 \([l, r]\) 内包含长度至少为 \(2\) 的回文子串的数的个数。

由回文子串的包含特性,显然只需要看是否包含长度恰好为 \(2\)\(3\) 的回文子串。

  • 长度为 \(2\) \(\rightarrow\) 存在某一对相邻位的数字相同
  • 长度为 \(2\) \(\rightarrow\) 存在某一对相隔 \(1\) 位的两位数字相同

需要设计 \(limit\)\(lead0\)\(last\)\(last2\)\(lastsame\)\(last2same\) 六种状态 ,其中 \(last2\) 表示当前位的上一位的上一位的数字;\(lastsame\) 表示当前前缀是否存在相邻位相同;\(last2same\) 同理。

code

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}\)

code

P4124

需要设计的状态比较多,但都是一眼。

code

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\) 的状态。

code

CF628D

code

CF855E

Q:计算 \([l, r]\) 内,满足在 \(b\) 进制下,\(0\backsim b-1\) 均出现偶数次的数的个数。

设计计状态 \(state\),每一位表示对应数字出现次数的奇偶性。

注意这道题是多测,如果对于每一次 \(b,l,r\) 都清空原来计算过的状态,代价显然太高。

code

posted @ 2026-02-12 00:14  小橘奏  阅读(12)  评论(0)    收藏  举报