题目描述
将整数 \(n\) 分成 \(k\) 份,且每份不能为空,任意两个方案不相同(不考虑顺序)。
例如:\(n = 7,k = 3\),下面三种分法被认为是相同的:
1,1,5; 1,5,1; 1,1,5.
问有多少种不同的分法。
输入格式
两个整数, \(n\) 和 \(k\) 。
输出格式
输出不同的分法数。
样例
输入样例
7 3
输出样例
4
样例说明
四种分法为:1,1,5; 1,2,4; 1,3,3; 2,2,3.
数据范围与提示
对于 \(100\%\) 的数据,\(6<n\leq200,2\leq k\leq6\)。
分析 -
对于整数 \(n\) 的划分,我们可以从 \(1\) 开始,一步步考虑。
-
首先,我们定一个数组 \(f[i][j]\) ,表示从 \(1\) 到 \(i\) 中,分成 \(j\) 份的分法有多少种。
-
那么我们首先可以确定的是 当 \(i < j\) 的时候,\(f[i][j]=0\),因为我们明显无法将 \(i\) 个整数分成 \(j\) 份,且每份都不为空。
-
当 \(i = j\) 的时候,\(f[i][j] = 1\),也就是 \(i\) 分成 \(j\) 份,且每份都为 \(1\)。
-
当 \(i>j\) 的时候,\(f[i][j]=f[i-1][j-1]+f[i-j][j]\),
- 对于前半种情况,是分成的 \(j\) 份中至少有一份为 \(1\),又因为题目说顺序不同认为是同种方案,所以,这种情况可以等同为 \(f[i - 1][j-1]\)。
- 对于后半种情况,是分成的 \(j\) 份中没有一份为 \(1\),那么我们可以考虑将 \(j\) 份都减少 \(1\) 来算方案数,也就是 \(f[i-j][j]\),那么对于 \(f[i-j][j]\) 我们可以继续分下去,直到变成第一种情况或者是边界。
-
因此,我们采用递推来解这一题。
#include <bits/stdc++.h>
using namespace std;
int n, k;
long long f[250][10];
int main (void) {
cin >> n >> k;
for (int i = 1; i <= n; ++i)
for (int j = 1; j <= k; ++j)
if (i < j) f[i][j] = 0;
else if (i == j) f[i][j] = 1;
else f[i][j] = f[i - 1][j - 1] + f[i - j][j];
cout << f[n][k];
return 0;
}
Copyright ©2021 Juro