整數劃分 --- 乙個老生長談的問題:
1) 練練組合數學能力.
2) 練練遞迴思想
3) 練練dp
總之是一道經典的不能再經典的題目:
這道好題求:
1. 將n劃分成若干正整數之和的劃分數。
2. 將n劃分成k個正整數之和的劃分數。
3. 將n劃分成最大數不超過k的劃分數。
4. 將n劃分成若干奇正整數之和的劃分數。
5. 將n劃分成若干不同整數之和的劃分數。
1.將n劃分成不大於m的劃分法:
1).若是劃分多個整數可以存在相同的:
dp[n][m]= dp[n][m-1]+ dp[n-m][m] dp[n][m]表示整數 n 的劃分中,每個數不大於 m 的劃分數。
則劃分數可以分為兩種情況:
a.劃分中每個數都小於 m,相當於每個數不大於 m- 1, 故劃分數為 dp[n][m-1].
b.劃分中有乙個數為 m. 那就在 n中減去 m ,剩下的就相當於把 n-m 進行劃分, 故劃分數為 dp[n-m][m];
2).若是劃分多個不同的整數:
dp[n][m]= dp[n][m-1]+ dp[n-m][m-1] dp[n][m]表示整數 n 的劃分中,每個數不大於 m 的劃分數。
同樣劃分情況分為兩種情況:
a.劃分中每個數都小於m,相當於每個數不大於 m-1,劃分數為 dp[n][m-1].
b.劃分中有乙個數為 m.在n中減去m,剩下相當對n-m進行劃分,
並且每乙個數不大於m-1,故劃分數為 dp[n-m][m-1]
2.將n劃分成k個數的劃分法:
方法可以分為兩類:dp[n][k]= dp[n-k][k]+ dp[n-1][k-1];
第一類: n 份中不包含 1 的分法,為保證每份都 >= 2,可以先拿出 k 個 1 分到每乙份,然後再把剩下的 n- k 分成 k 份即可,分法有: dp[n-k][k]
第二類: n 份中至少有乙份為 1 的分法,可以先那齣乙個 1 作為單獨的1份,剩下的 n- 1 再分成 k- 1 份即可,分法有:dp[n-1][k-1]
另一種方式:
dp[i,j]表示將i分成j份的方案數。
dp[i,j]:=dp[i-j,1]+dp[i-j,2]+dp[i-j,3]+…+dp[i-j,j-1]+dp[i-j,j];
時間複雜度是n*k^2。o(n*k)的方法:
由於,dp[i,j]=dp[i-j,1]+dp[i-j,2]+…+dp[i-j,j];
dp[i-1,j-1]=dp[(i-1)-(j-1),1]+dp[(i-1)-(j-1),2]+…+dp[(i-1)-(j-1),j-1]
=dp[i-j,1]+dp[i-j,2]+…+dp[i-j,j-1];
因此,dp[i,j]=dp[i-j,1]+dp[i-j,2]+…+dp[i-j,j-1]+dp[i-j,j]
=dp[i-1,j-1]+dp[i-j,j];
hzwer思路 orz
就是它這個分法比較特殊
不是一堆一堆分的
而是每次把每一堆+1,或者把空堆變成1
拓展:還有乙個劃分為不超過k組的問題
就是看成與本題類似,但是可以有元素為0
得到:dp[i,j]=dp[i-j,j]+dp[i,j-1]
區別就是dp[i,j-1]中i沒有-1
參照hzwer的思想,因為元素可以為0,就算某一堆為空堆,總數也不需要-1
3.將n劃分成若干奇數的劃分法:(不懂)
g[i][j]:將i劃分為j個偶數
f[i][j]:將i劃分為j個奇數
g[i][j] = f[i - j][j];
f[i][j] = f[i - 1][j - 1] + g[i - j][j]
劃分數問題
問題描述 有n個無區別的物品,將它們劃分成不超過m組,求出劃分方法數 這是一道經典的不能再經典的題目,當然也有不同的定義方式,下面將從兩種方式來分析這個問題 把n個同樣的蘋果放在m個同樣的盤子裡,允許有的盤子空著不放,問共有多少種不同的分法?用k表示,5,1,1和1,5,1 是同一種分法 放蘋果的問...
整數劃分(數的m劃分)
includeusing namespace std int f int n,int m n代表數字,m代表n的m劃分 int main 方式二 動態規劃 dp i j 表示i的j次劃分的情況種數 狀態轉移方程為dp i j dp i j j dp i 1 j 1 1.dp i 1 j 1 表示劃分...
計數DP 劃分數
蒜頭君特別喜歡數學。今天,蒜頭君突發奇想 如果想要把乙個正整數 n n 分解成不多於 k k 個正整數相加的形式,那麼一共有多少種分解的方式呢?蒜頭君覺得這個問題實在是太難了,於是他想讓你幫幫忙。共一行,包含兩個整數 n 1 leq n leq 300 n 1 n 300 和 k 1 leq k l...