将整数n分成k份,且每份不能为空,任意两种划分方案不能相同(不考虑顺序)。 例如:n=7,k=3,下面三种划分方案被认为是相同的。 1 1 5
1 5 1
5 1 1 问有多少种不同的分法。
输入描述 Input Description输入:n,k (6<n<=200,2<=k<=6)
输出描述 Output Description输出:一个整数,即不同的分法。
样例输入 Sample Input7 3
样例输出 Sample Output4
数据范围及提示 Data Size & Hint{四种分法为:1,1,5;1,2,4;1,3,3;2,2,3;}
本题的状态转移方程为: d[i][j]=d[i-j][j]+d[i-1][j-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]; 由于, 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];
代码如下:
#include<iostream> using namespace std; int d[1000][10], n, k; int main() { cin >> n >> k; d[0][0] = 1; for (int i = 1; i <= n; i++) d[i][1] = 1; for (int i = 1; i <= n; i++) for (int j = 1; j <= k; j++) if (i >= j) d[i][j] = d[i - j][j] + d[i - 1][j - 1]; cout << d[n][k]<<endl; return 0; }