数位DP 入门学习详解

数位DP

什么是数位DP

数位DP是DP的一种,顾名思义,按每一个数位来进行DP。

什么时候使用

题目的要求与一个数字相关,并且它能通过每一个数位来进行转移。
例题:求所有 n n n位数中能被 m m m整除的数的个数。

怎么使用

一般的DP是多维的,首先会有一维表示的是当前到了第几位,通常情况这一维可以使用滚动。
其它的就是根据题目的实际要求了,如例题就需要一维来记录除以 m m m的余数。
以例题为例,我们来讲讲数位DP怎么实现。

状态与转移

我们设 f [ i ] [ j ] f[i][j] f[i][j]表示当前到了第 i i i位,除以 m m m的余数为 j j j的方案数。
一般是从高位往低位DP,因为最高位不能为 0 0 0,所以我们对 i = 1 i=1 i=1的情况先处理好:
f [ 1 ] [ i m o d    m ] = 1 ( 1 ≤ i ≤ 9 ) f[1][i\mod m]=1(1≤i≤9) f[1][imodm]=1(1i9)

接着我们用第 i i i位的状态去更新第 i + 1 i+1 i+1位的状态,每次枚举当前在第 i + 1 i+1 i+1位加入 k k k
想想怎么转移?
对于当前的余数 j j j,在末尾加入了 k k k,余数变成什么?
根据同余的性质,我们自然可以得到:余数变成了 ( j ∗ 10 + k ) m o d    m (j*10+k)\mod m (j10+k)modm
所以,状态转移方程如下:

f [ i + 1 ] [ ( j ∗ 10 + k ) m o d    m ] + = f [ i ] [ j ] ( 1 ≤ i < n , 0 ≤ j < m , 0 ≤ k ≤ 9 ) f[i+1][(j*10+k)\mod m]+=f[i][j](1≤i<n,0≤j<m,0≤k≤9) f[i+1][(j10+k)modm]+=f[i][j](1i<n0j<m0k9)

最后的答案是什么?
首先,第一维自然是 n n n,那么第二维取什么值呢?
显而易见,要求是 m m m的倍数,所以第二维是 0 0 0
综上所述,最后的答案是 f [ n ] [ 0 ] f[n][0] f[n][0]

更多拓展

【数位DP】JZOJ 5831. 【NOIP提高A组模拟2018.8.18】 number

你可能感兴趣的:(动态规划)