數字dp 模板 老年康復

2022-02-03 22:44:00 字數 2989 閱讀 1359

學習部落格:

戳這裡戳這裡

「在資訊學競賽中,有這樣一類問題:求給定區間中,滿足給定條件的某個d 進製數或

此類數的數量。所求的限定條件往往與數字有關,例如數字之和、指定數碼個數、數的大小

順序分組等等。題目給定的區間往往很大,無法採用樸素的方法求解。此時,我們就需要利

用數字的性質,設計log(n)級別複雜度的演算法。解決這類問題最基本的思想就是「逐位確定」

的方法。下面就讓我們通過幾道例題來具體了解一下這類問題及其思考方法。」——劉聰

事實上,為什麼會想到用數字dp來做,就是因為限定條件往往和數字有關,而仔細地樸素的暴力方法中,所做的重複的工作太多。這樣的條件會使得dp(記憶化搜尋)有用武之地。

比如如果我們要統計[0,54321]中滿足某個條件的個數,需要將其拆分為

[00000,09999][10000,19999],[20000,29999],[30000,39999],[40000,49999],

[50000,50999],[51000,51999],[52000,52999],[53000,53999],

[54000,54099],[54100,54199],[54200,54299],

[54300,54309],[54310,54319],

[54320,54321]

為什麼要這麼分呢?隨便舉個例子,如果我們統計過了[0000,9999]中的滿足條件(或者其他各種不滿足條件的狀態)的個數,那麼分別在加上字首,就可以判斷出有多少個滿足條件的個數。目的是為了將大的區間劃分為小的區間進行求解。

因此,總結一句話,數字dp減少的運算量為:前面幾位固定,後面幾位可以任意取的個數統計。

模板:

1 typedef long

long

ll;2

int a[20

];3 ll dp[20][state];//

不同題目狀態不同

4 ll dfs(int pos,/*

state變數

*/,bool lead/*

前導零*/,bool limit/*

數字上界變數

*/)//

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

//計算完,記錄狀態

26if(!limit && !lead) dp[pos][state]=ans;

27/*

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

*/28

return

ans;29}

30ll solve(ll x)

3138

return dfs(pos-1

/*從最高位開始列舉

*/,/*

一系列狀態

*/,true,true);//

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

40int

main()

4148 }

view code

練手題目1:戳這裡

題意:求1-n內有多少個數滿足各位之和整除該數。

解題思路:數字dp,列舉各位之和。

附ac**:

1 #include2 #include3 #include4 #include

5 #include

6using

namespace

std;

7 typedef long

long

ll;8

int a[22

];9 ll dp[20][220][220];//

不同題目狀態不同

10int

mod;

11 ll dfs(int pos, int state/*

state變數

*/, int r/*

其他記錄點,在這裡是餘數

*/, bool limit/*

數字上界變數*/)

1234

//計算完,記錄狀態

35if(!limit) dp[pos][state][r] =ans;

36/*

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

*/37

return

ans;38}

39ll solve(ll n)

4048 ll ans = 0;49

for(int i = 1; i <= 9 * pos; ++i)//

列舉模50

56return

ans;57}

58int

main()

5968

6970 }

view code

練手題目2:戳這裡

題意:求l-r中有多少個數滿足各位》0的數不大於三個。

解題思路:模板題略作修改。

附ac**:

1 #include 2

using

namespace

std;

3const

int maxn = 22

;4 typedef long

long

ll;5

inta[maxn];

6ll dp[maxn][maxn];

7 ll dfs(int pos, int stat, bool

lim)820

}21if(!lim && stat <= 3) dp[pos][stat] =ans;

22return

ans;23}

24ll solv(ll x)

2532

33return dfs(pos, 0, true

);34}35

intmain()

3646

return0;

47 }

view code

數字DP入門 數字DP模板

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

數字dp 模板

dp pos,狀態變數.限制布林 if limit dp 狀態 a 已經求出對應狀態值下的結果了 記錄下來 return a 所以 數字dp其實就是一種求解有關於l到r有多少個符合條件的數目類似的統計問題的解題思路 一遍遍數字列舉太慢 不如我們根據條件列舉數字 數字dp本質上是記憶化搜尋 我們需要在...

數字DP模板

數字dp問題,大多是統計數量,通常用按位處理的方法解決。具體為 詢問 l,r l,r l,r 中滿足某一條件的數。利用字首和的思想,我們可以把問題簡化,即轉化為詢問 1,r 1,r 1,r 和 1,l 1 1,l 1 1,l 1 實現時,常常使用記憶化搜尋,由於有很多限制條件,所以常常增加幾維狀態,...