題目描述:
將n個無區別的物品,劃分成不超過m組,求出劃分方法總數,輸出總數模M的餘數。
樣例輸入:
4 3 10000
將4劃分爲不超過3項:,有4種劃分方法,所以輸出
樣例輸出
4
算法
用動態規劃,表示將劃分成不超過組。
比如說dp[3][7]表示將7劃分成不超過3組,劃分方法如下:
一共有8種劃分方法,現在觀察上述8種劃分,既然是劃分成不超過3項,乾脆給未滿3項的劃分補0,使之變成3項。這樣一來,上述8種劃分方式就被分爲不含0的劃分和含0的劃分。
對於所有將4劃分成不超過3項:1+1+2、2+2+0、1+3+0、4+0+0(補0保證每種劃分都是3項),將每種劃分中每一項都加1:2+2+3、2+2+1、2+4+1、5+1+1,發現這些都是將7劃分成不超過3項的結果中,不含0的劃分。
反之,7劃分成不超過3項的結果中,所有不含0的劃分,都能將每一項減1變成將4劃分爲不超過3項。
所以,中不含0的劃分就等於。
對於所有將7劃分爲不超過2項的劃分結果,加個0便成爲了將7劃分爲不超過3項的結果。
對於所有將7劃分爲不超過3項的劃分結果中,含0的劃分,去掉一個0便得到了將7劃分爲不超過2項的劃分結果。
所以,中含0的劃分就等於。
綜上所述,遞推關係爲:
初始值爲:
沒有任何非零數是0個數的和,數字0無論分成幾項之和都只有一種方式。
代碼
#include<stdio.h>
#define maxn 1005
int n, m, M;
int dp[maxn][maxn];
int main(){
while(scanf("%d %d", &n, &m)==2){
for(int i = 0;i <= m;i++){
dp[i][0] = 1;
}
for(int j = 1;j <= n;j++){
dp[0][j] = 0;
}
scanf("%d", &M);
for(int i = 1;i <= m;i++){
for(int j = 1;j <= n;j++){
if(j>=i){
dp[i][j] = dp[i-1][j] + dp[i][j-i];
}
else{
dp[i][j] = dp[i-1][j];
}
}
}
printf("%d\n", dp[m][n]%M);
}
return 0;
}