基礎演算法之動態規劃 數字DP

2021-10-11 04:05:16 字數 3206 閱讀 8634

數字dp一般用來統計乙個區間[l,

r]

[l,r]

[l,r

]中滿足條件f(i

)f(i)

f(i)

的數的個數。條件f

(i

)條件 f(i)

條件f(i)

一般與數的大小無關,而與數的組成有關(即數字,個位、十位、百位…),因此數的大小對複雜度的影響很小。

數字dp本質是對暴力列舉的優化,使得新的列舉方式滿足dp性質,從而能進行記憶化。

對於乙個求區間[l,

r]

[l,r]

[l,r

]滿足條件的數的個數,最簡單暴力的做法如下:

for

(int i = l; i <= r; i ++)if

(check

(i)) ans ++

;

然而這樣列舉沒有狀態可言,不方便記憶。

控制上界列舉。從最高位開始向下列舉,例如:n = 213,那麼從百位開始列舉,百位可能的情況有0,1,2;然後在每一位上的列舉的數,組合起來都不能超過上界213。這樣就計算出了從1−n

1-n1−

n所有符合條件的方案f[n],然後利用字首和的思想就可以統計出區間[l,

r]

[l,r]

[l,r

]滿足條件的方案數f[r] - f[l - 1]

求區間 f[l, r] = f[r] - f[l - 1]

分情況討論,從集合劃分的角度分析問題

求給定區間 [x,

y]

[x,y]

[x,y

] 中滿足下列條件的整數個數:這個數恰好等於 k

kk 個互不相等的 b

bb 的整數次冪之和。

例如,設 x=15

,y=20

,k=2

,b=2

x=15,y=20,k=2,b=2

x=15,y

=20,

k=2,

b=2,則有且僅有下列三個數滿足題意:

17 =2

4+20

17=2^4+2^0

17=24+

2018 =2

4+21

18=2^4+2^1

18=24+

2120 =2

4+22

20=2^4+2^2

20=24+

22輸入格式

第一行包含兩個整數 x

xx 和 y

yy,接下來兩行包含整數 k

kk 和 bbb。

輸出格式

只包含乙個整數,表示滿足條件的數的個數。

資料範圍1≤x

≤y≤2

31−

11≤x≤y≤2^−1

1≤x≤y≤

231−

1,1 ≤k

≤20

1≤k≤20

1≤k≤20,2≤

b≤

102≤b≤10

2≤b≤10

輸入樣例

15 2022

輸出樣例

如果將數n

nn表示為乙個n

nn位b

bb進製數的形式: a[n

−1]a

[n−2

]...

a[0]

a[n-1]a[n-2]...a[0]

a[n−1]

a[n−

2]..

.a[0

],其中0≤a

[i

]<

b0 ≤ a[i] < b

0≤a[i]

<

b,那麼求區間[0,

n]

[0,n]

[0,n

]所有滿足條件的方案,就是求a[n

−1]a

[n−2

]...

a[0]

a[n-1]a[n-2]...a[0]

a[n−1]

a[n−

2]..

.a[0

]中有k

kk個1、其它位均為0的數的個數。

因為是統計區間[0,

n]

[0,n]

[0,n

]上的每乙個數字,所以列舉的上限為n

nn,所有符合條件的方案可以根據n

nn的第i位數字x的情況分為3類:

x = 1,則第i位上可以取01

x = 0,則第i位上也只能取 0 ,所以直接計算後面數字的取值情況就可以了。

對於最後一位還要進行單獨討論,如果在最後一位 ,所有的k1都已經取好了,也就是k==last了,那麼最後一位可以是0,總的方案數增加1

#include

#include

using

namespace std;

const

int n =35;

int f[n]

[n];

//f[i][j]表示從i個數中選j個數的方案數

int k, b;

//處理f[i][j]

void

init()

}//求區間[0...n]中所有滿足條件的數的個數

intdp

(int n)

else

//x==1,表示第i位取1,則情況數需要對下乙個數字分情況討論}if

(!i && last == k) res ++

;//最後一位單獨判斷

}return res;

}int

main()

動態規劃之數字dp

數字dp,字面意思理解就是在數字的每一位上面去dp,動態規劃一般有兩種 遞推,記憶化搜尋 dfs 這裡就是用的記憶化。一般這種用在計數上面,對那些數字上面有限制的計數。這裡上一道模板題 題中就是要你統計1 n裡有 49 的個數。dp pos sta 表示到第pos位,狀態為sta的總數。我們一般是從...

演算法之動態規劃DP

若要解乙個給定問題,我們可以解其不同部分 即子問題 再根據子問題的解以得出原問題的解。通常許多子問題非常相似,為此動態規劃法試圖僅僅解決每個子問題一次,從而減少計算量 一旦某個給定子問題的解已經算出,則將其記憶化儲存,以便下次需要同乙個子問題解之時直接查表。這種做法在重複子問題的數目關於輸入的規模呈...

基礎演算法之動態規劃 狀態壓縮DP

狀態壓縮是指用二進位制表示集合的方式對狀態進行壓縮,將其表示為乙個整數。例如 用二進位制表示乙個集合的子集。集合 s s s 那麼二進位制數 01001 2 01001 2 01001 2 表示的就是s ss的乙個子集s s s 該子集可以用乙個十進位制數9 99來表示。狀態壓縮dp其實是動態規劃類...