數字dp顧名思義就是對數字運用dp思想,將每位數看成下一位的子狀態,即個位看成十位的子狀態,十位看成百位的子狀態。下面給出狀態方程:
dp[i][j]=
∑dp[i-1][k](k=0,1,2,3...9)
dp[i][j] 表示i位數,首位是j的數字有多少符合要求的,我們從低位逐步遞推求到高位。
下面拿一道入門題來具體說明:hdu 2089 不要62
傳送門如何求滿足要求的種類數呢,我們先不考慮62和4的問題,那麼 就拿335舉例,當i<3時,就用遞推公式,個位的各個數就是它自身,十位的各個數就等於個位的加和 即:dp[1][0]=1,dp[1][1]=1,dp[1][2]=1。。。。dp[2][0]等於個位的加和,即:dp[2][0]=10,dp[2][1]=10,dp[2][2]=10。。。。以此類推 通過dp[3][0],dp[3][1],dp[3][2]求得首位數字小於3的滿足條件的三位數,dp[3][0]求得的數是001,052,093...也就是所有滿足條件的一位或兩位數……我們求得所有的2xx,1xx,0xx.
當i=3時,對應dp[3][3],但是滿足要求的數有336,347,358……這些數超過了335……
首位只能是3,也就是第一位已經選完了,那麼我們只要選擇滿足小於35的數字就可以了。和上面同理,我們只要求出dp[2][0],dp[2][1],dp[2][2],dp[2][3],dp[2][4]就可以求出首位小於3的兩位數。這時求得的是32x,31x,30x。
然後我們求所有小於5的數字就ok。小於5也就是dp[0],dp[1],dp[2],dp[3],dp[4]。這時求得的是53x.
現在要考慮62和4的情況:
如果某一位數字為4,如77432的第三位(從左向右看)是4,那麼我們依次求出6***x,5***x,...,0***x,76***,75***,...,70***,773xx,773xx,...,770xx,我們接來下需要求的是7742x....7740x,但這時所求的數是774xx的數,必然含有4,所以這時我們停止。
對於62,如果某一位數字是6,如5675,我們求完5***,4***,...0***之後再求56xx時,注意566x,565x,..,563x,561x,沒有562x。如果數字中含有62,如5627,那麼同4,求到562x的時候就應該停止繼續求下去了。
下面附上**:
#include #include #include using namespace std;
int dp[10][10];
int num[10];
int solve(int n)
num[len+1]=0;
for(i=len;i>=1;i--){
for(j=0;j
數字DP入門 數字DP模板
數字dp是一種計數用的dp,一般就是要統計乙個區間 le,ri 內滿足一些條件數的個數。所謂數字dp,字面意思就是在數字上進行dp咯。數字還算是比較好聽的名字,數字的含義 乙個數有個位 十位 百位 千位.數的每一位就是數字啦!之所以要引入數字的概念完全就是為了dp。數字dp的實質就是換一種暴力列舉的...
數字dp入門
數字dp,顧名思義 對數的位數進行操作。一般 題目會與數的位數相關。數字dp最重要的是其dp陣列的確定,根據需要 可以確定多維dp陣列,一般dp陣列的每一對下標 都只能唯一確定乙個狀態,或者 對結果並不影響。dp陣列一定會有一維表示 當前列舉到的 位數。模版 如 此處設立的dp陣列為二維 int d...
數字dp入門
數字dp是一種計數用的dp,一般就是要統計乙個區間 le,ri 內滿足一些條件數的個數。所謂數字dp,字面意思就是在數字上進行dp咯。數字還算是比較好聽的名字,數字的含義 乙個數有個位 十位 百位 千位 數的每一位就是數字啦!之所以要引入數字的概念完全就是為了dp。數字dp的實質就是換一種暴力列舉的...