數字dp入門

2021-10-24 18:52:45 字數 2417 閱讀 7614

數字dp是一種計數用的dp,一般就是要統計乙個區間[le,ri]內滿足一些條件數的個數。所謂數字dp,字面意思就是在數字上進行dp咯。數字還算是比較好聽的名字,數字的含義:乙個數有個位、十位、百位、千位…數的每一位就是數字啦!

之所以要引入數字的概念完全就是為了dp。數字dp的實質就是換一種暴力列舉的方式,使得新的列舉方式滿足dp的性質,然後記憶化就可以了。

兩種不同的列舉:對於乙個求區間[le,ri]滿足條件數的個數,最簡單的暴力如下:

for

(int i=le;i<=ri;i++)if

(right

(i)) ans++

;

然而這樣列舉不方便記憶化,或者說根本無狀態可言。

新的列舉:控制上界列舉,從最高位開始往下列舉,例如:ri=213,那麼我們從百位開始列舉:百位可能的情況有0,1,2(覺得這裡列舉0有問題的繼續看)

然後每一位列舉都不能讓列舉的這個數超過上界213(下界就是0或者1,這個次要),當百位列舉了1,那麼十位列舉就是從0到9,因為百位1已經比上界2小了,後面數字列舉什麼都不可能超過上界。所以問題就在於:當高位列舉剛好達到上界是,那麼緊接著的一位列舉就有上界限制了。具體的這裡如果百位列舉了2,那麼十位的列舉情況就是0到1,如果前兩位列舉了21,最後一位之是0到3(這一點正好對於**模板裡的乙個變數limit 專門用來判斷列舉範圍)。最後乙個問題:最高位列舉0:百位列舉0,相當於此時我列舉的這個數最多是兩位數,如果十位繼續列舉0,那麼我列舉的就是以為數咯,因為我們要列舉的是小於等於ri的所以數,當然不能少了位數比ri小的咯! (這樣列舉是為了無遺漏的列舉,不過可能會帶來乙個問題,就是前導零的問題,模板裡用lead變數表示,不過這個不是每個題目都是會有影響的,可能前導零不會影響我們計數,具體要看題目)

由於這種新的列舉只控制了上界所以我們的main函式總是這樣:

nt main()

統計[1,ri]數量和[1,le-1],然後相減就是區間[le,ri]的數量了,這裡我寫的下界是1,其實0也行,反正相減後就沒了,注意題目中le的範圍都是大於等於1的(不然le=0,再減一就gg了)

在講例題之前先講個基本的動態模板(先看後面的例題也行):dp思想,列舉到當前位置pos,狀態為state(這個就是根據題目來的,可能很多,畢竟dp千變萬化)的數量(既然是計數,dp值顯然是儲存滿足條件數的個數)

typedef

long

long ll;

int a[20]

; ll dp[20]

[state]

;//不同題目狀態不同

ll dfs

(int pos,

/*state變數*/

,bool lead/*前導零*/

,bool limit/*數字上界變數*/

)//不是每個題都要判斷前導零

//計算完,記錄狀態 if(

!limit &&

!lead) dp[pos]

[state]

=ans;

/*這裡對應上面的記憶化,在一定條件下時記錄,保證一致性,當然如果約束條件不需要考慮lead,這裡就是lead就完全不用考慮了*/

return ans;

} ll solve

(ll x)

return

dfs(pos-

1/*從最高位開始列舉*/

,/*一系列狀態 */

,true

,true);

//剛開始最高位都是有限制並且有前導零的,顯然比最高位還要高的一位視為0嘛

}int

main()

}

下面是一道模板題

【hdu2089】不要六二

#include

#include

using

namespace std;

typedef

long

long ll;

ll a[20]

;ll dp[20]

[2];

ll dfs

(ll pos,ll pre,ll state,

bool limit)

//若state為1說明前一位為6if(

!limit)dp[pos]

[state]

=ans;

//儲存

return ans;

}ll solve

(ll x)

//執行完後ans會多+1

return

dfs(pos-1,

0,0,

true);

//從高位開始dp,第一位數字只能取到a[pos]所以limit置為true

}int

main()

return0;

}

數字DP入門 數字DP模板

數字dp是一種計數用的dp,一般就是要統計乙個區間 le,ri 內滿足一些條件數的個數。所謂數字dp,字面意思就是在數字上進行dp咯。數字還算是比較好聽的名字,數字的含義 乙個數有個位 十位 百位 千位.數的每一位就是數字啦!之所以要引入數字的概念完全就是為了dp。數字dp的實質就是換一種暴力列舉的...

數字DP入門

數字dp顧名思義就是對數字運用dp思想,將每位數看成下一位的子狀態,即個位看成十位的子狀態,十位看成百位的子狀態。下面給出狀態方程 dp i j dp i 1 k k 0,1,2,3.9 dp i j 表示i位數,首位是j的數字有多少符合要求的,我們從低位逐步遞推求到高位。下面拿一道入門題來具體說明...

數字dp入門

數字dp,顧名思義 對數的位數進行操作。一般 題目會與數的位數相關。數字dp最重要的是其dp陣列的確定,根據需要 可以確定多維dp陣列,一般dp陣列的每一對下標 都只能唯一確定乙個狀態,或者 對結果並不影響。dp陣列一定會有一維表示 當前列舉到的 位數。模版 如 此處設立的dp陣列為二維 int d...