1. 程式人生 > >整數劃分問題(二)

整數劃分問題(二)

pro col void ++ cal -c 一行 測試 不同的

總時間限制:
200ms
內存限制:
65536kB
描述

將正整數n 表示成一系列正整數之和,n=n1+n2+…+nk, 其中n1>=n2>=…>=nk>=1 k>=1
正整數n 的這種表示稱為正整數n 的劃分。

輸入
標準的輸入包含若幹組測試數據。每組測試數據是一行輸入數據,包括兩個整數N 和 K。
(0 < N <= 50, 0 < K <= N)
輸出
對於每組測試數據,輸出以下三行數據:
第一行: N劃分成K個正整數之和的劃分數目
第二行: N劃分成若幹個不同正整數之和的劃分數目
第三行: N劃分成若幹個奇正整數之和的劃分數目
樣例輸入
5 2
樣例輸出
2
3
3
提示
第一行: 4+1, 3+2,
第二行: 5,4+1,3+2
第三行: 5,1+1+3, 1+1+1+1+1+1
來源 openjudge
參考代碼及分析
/**

1、N劃分成K個正整數之和的劃分數目
i:要被劃分的數,這裏假設為5;j:劃分成j個正整數,這裏假設為2;
dp[i][j]
①沒有1的情況
dp[i-j][j],因為要分成j份,所以從i中拿出j個1,把i-j分成j份,每一個份加上1就是沒有1的情況了。
栗子:3,2;三分成兩份,1+2,每份加上1即2+3,就是沒有1的情況。
②有至少有一個1的情況
dp[i-1][j-1],先從i中拿出1算做一份,還剩下j-1份,把i-1分成j-1份就是有1的情況了。
栗子:4,1,4分成1份,4,再加上1的份,即4+1,就是有1的情況。

2、N劃分成若幹個不同正整數之和的劃分數目
i:要被劃分的數,這裏假設為5;j:劃分數都不大於j,這裏假設為5
dp[i][j]
因為劃分數都是不同的,所以每一個劃分數要麽有,要麽沒有所以分兩種情況
①劃分數沒有j的情況
dp[i][j-1]
②劃分數有j的情況
dp[i-j][j-1]

3、N劃分成若幹個奇正整數之和的劃分數目
g[i][j]:i,被劃分的數;j,劃分成j個偶數;
f[i][j]:i,被劃分的數;j,劃分成j個奇數;
①在i中拿出j個1,將i-j分成j個奇數,將1再加上就成了j個偶數
g[i][j]=f[i-j][j];
分成奇數又成有1和沒有1的情況
①有1的情況
g[i-j][j],劃分成偶數,每個偶數減1就是劃分成奇數有1的情況
f[i-1][j-1],劃分成奇數,把1的份去掉
*/ #include <iostream> #include <string.h> using namespace std; int n,k; int res1[51][51],res2[51][51],g[51][51],f[51][51]; int res3; void dp(); int main() { while(cin>>n>>k){ dp(); } return 0; } void dp(){ for(int i=0;i<n;i++){///關於邊界問題 res1[i][0]=0; res1[
0][i]=0; res2[i][0]=0; res2[0][i]=0; } for(int i=1;i<=n;i++){ for(int j=1;j<=n;j++){ if(i==j){ res1[i][j]=1;//只有劃分成i個1的情況 res2[i][j]=res2[i][j - 1] + 1;;//包含j的情況是自身所以只有1種 } if(i<j){ res1[i][j]=0;//不可能將i劃分成比i大個份 res2[i][j]=res2[i][i]; } if(i>j){ res1[i][j]=res1[i-j][j]+res1[i-1][j-1]; res2[i][j]=res2[i][j-1]+res2[i-j][j-1]; } } } f[0][0]=1;//當i=1,j=1時,f[1][1]=f[0][0]+g[i-j][j] for (int i=1;i<=n;i++) { for (int j=1;j<=i;j++) { g[i][j]=f[i-j][j]; f[i][j]=f[i-1][j-1]+g[i-j][j]; } } cout<<res1[n][k]<<endl; cout<<res2[n][n]<<endl; res3=0; for(int i=1;i<=n;i++){ res3+=f[n][i]; } cout<<res3<<endl; }

整數劃分問題(二)