數字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
位上可以取0
或1
x = 0
,則第i
位上也只能取 0 ,所以直接計算後面數字的取值情況就可以了。
對於最後一位還要進行單獨討論,如果在最後一位 ,所有的k
個1
都已經取好了,也就是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其實是動態規劃類...