数位dp学习笔记

目录

  • 数位dp学习笔记
    • 引入
    • 练习题目
      • LG2567
      • ZJOI2010
      • LG3413
    • 后记

数位dp学习笔记

在解决一类数位问题的时候,我们发现有些状态是多余的(比如中间的某些数),完全可以合并一起计数,这就是数位dp

具体地说,按每一位进行dp,枚举长度和与要用到的数字

引入

一道例题:求n位数中能被m整除的个数

定义一个状态:\(f[i][j]\)表示当前是第\(i\)位,除以\(m\)的余数为\(j\)

初始情况:\(f[1][i]=1(1\leq i \leq 9)\)

对于下一位\(k\),余数变成\(j*10+k \pmod m\)

转移就是\(f[i+1][(j*10+k) \pmod m]+=f[i][j]\)

由于最后要求倍数,答案为\(f[n][0]\)

练习题目

LG2567

求[L,R]中不含前导零且相邻两个数字之差至少为2的正整数

考虑求出前缀和

由于前导0比较,我们从低往高进行dp

设计状态:\(f[i][j]\)表示\(i\)位数,最高位为\(j\)的windy数个数

预处理出来之后分成三部分计算答案:

  1. 位数都小于此数
  2. 位数等于此数,但是最高位小于此数(前导0,不能和3合并)
  3. 位数等于次数,最高位也相等,考虑枚举有多少位相等

其实有前导0的都可以这样搞计数,只是预处理方法不同

ZJOI2010

\(f[i][j]\)表示\(i\)位数,最高位为\(j\)的windy数个数

\(f[i][j][k]\)表示\(i\)位数,最高位为\(j\)\(k\)的个数

\(f[i+1][l][k]+=f[i][j][k]+[l=k]\)

统计答案就跟上面一样

LG3413

考虑长度大于等于三的回文子串一定包含长度为2或3的回文子串

所以只需要记录上两个选的数是什么就好了

初始状态,显然处理两位数的,如果两位相等则为1,不相等为0

后记

感觉都能一眼看出数位dp,也挺好推,主要是细节

所以不打算专门做这类题,考场上推一推就好了,细节处理就平时练其他题的时候锻炼一下

你可能感兴趣的:(数位dp学习笔记)