13 整數劃分 計數類DP

2022-09-16 14:33:12 字數 2392 閱讀 2812

每種劃分方式都是按照從大到小排序的

樣例分析:

5有7種劃分方式

5 = 5

5 = 4 + 1

5 = 3 + 2

5 = 3 + 1 + 1

5 = 2 + 2 + 1

5 = 2 + 1 + 1 + 1

5 = 1 + 1 + 1 + 1 + 1

解法一:用揹包問題的思想

把整數n看做乙個容量為n的揹包

然後一共有n個物品,每個物品的體積分別是1,2,3,...,n。(也就是n這個數的所有因子)

每種物品可以用無限次,所以是完全揹包問題

求恰好裝滿揹包的方案數

狀態表示:

集合:dp[i][j]表示從物品1~i中選,總體積恰好為j的選法的集合

屬性:數量

狀態計算:集合的劃分,同揹包問題

根據第i個物品選了幾個來劃分

狀態數量:n ^ 2

轉移數量:n(粗略估計的,比n小,應該為log n)

時間複雜度:n ^ 3

然後進行優化

二維做法

1 #include 2

using

namespace

std;

3const

int n = 1010, mod = 1e9 + 7;4

intdp[n][n];

5int

main()

11for (int i = 1; i <= n; i++) 17}

18}19 cout << dp[n][n] <

20return0;

21 }

然後再轉化為一維,再從小到大迴圈體積注意初值問題:求最大值時,當都不選時,價值顯然是 0

而求方案數時,當都不選時,方案數是 1(即前 i 個物品都不選的情況也是一種方案),所以需要初始化為 1

即需要這樣:

for  (int i = 0; i <= n; i++)

等價變形後: f[0] = 1

一維做法

1 #include 2

using

namespace

std;

3const

int n = 1010, mod = 1e9 + 7;4

intdp[n];

5int

main() 13}

14 cout << dp[n] <

15return0;

16 }

解法二:

ps : 最小值1 表示 :j個數的總和是i的數中最小的數為1

1 #include 2

using

namespace

std;

3const

int n = 1010, mod = 1e9 + 7;4

intdp[n][n];

5int

main() 13}

14int res = 0;15

for (int i = 1; i <= n; i++)

18 cout << res <

19return0;

20 }

NYOJ90 整數劃分(計數DP)

時間限制 3000 ms 記憶體限制 65535 kb 難度 3 描述 將正整數n表示成一系列正整數之和 n n1 n2 nk,其中n1 n2 nk 1,k 1。正整數n的這種表示稱為正整數n的劃分。求正整數n的不同劃分個數。例如正整數6有如下11種不同的劃分 6 5 1 4 2,4 1 1 3 3...

整數劃分(劃分dp)總結

寫了幾個題發現整數劃分是一類題,而不是一道題。具體題型 1 n相同元素放入m個相同的盤子 盤子允許為空 例題 放蘋果 poj 1664設dp i j 為 j 個元素放入i個盤子轉移方程 dp i j dp i 1 j 新新增乙個盤子,盤子為空 dp i j dp i j i i個盤子 各取出乙個 2...

計數DP 劃分數

蒜頭君特別喜歡數學。今天,蒜頭君突發奇想 如果想要把乙個正整數 n n 分解成不多於 k k 個正整數相加的形式,那麼一共有多少種分解的方式呢?蒜頭君覺得這個問題實在是太難了,於是他想讓你幫幫忙。共一行,包含兩個整數 n 1 leq n leq 300 n 1 n 300 和 k 1 leq k l...