因为这道题的变形和其原型,屡次都错了,专门做个笔记来记录一下
一.题目
一个正整数n可以表示成若干个正整数之和,形如:n=n1+n2+…+nk,其中n1≥n2≥…≥nk,k≥1n=n1+n2+…+nk,其中n1≥n2≥…≥nk,k≥1。
我们将这样的一种表示称为正整数n的一种划分。
现在给定一个正整数n,请你求出n共有多少种不同的划分方法。
输入格式 共一行,包含一个整数n。
输出格式 共一行,包含一个整数,表示总划分数量。
由于答案可能很大,输出结果请对10^9+7取模。
数据范围
1≤n≤1000
输入样例:
5
输出样例:
7
利用动态规划f[n][n]来表示这一状态,选取前n个数中的一些数组成n,有多少种组成方案。光听这个描述有没有一种很像背包体积的问题?并且这n个物体并没有限制次数,所以是完全背包问题。那这就是一个完全背包问题的变形。
动态规划就要考虑到状态转移方程:对于当前状态前i个数拼凑成j,那么它其实是有前i-1个数来拼凑的,可以不选第i-1个数,也可以选1个,选2个,选无限个
f[i][j] = f[i - 1][j] + f[i - 1][j - i] + f[i - 1][j - 2 * i] + ...
f[i][j - i] = f[i - 1][j - i] + f[i - 1][j - 2 * i] + ...所以我们可以将f[i][j] = f[i - 1][j] + f[i][j - i]
完整代码:
import java.util.Scanner;
public class IntegerDivsion {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[][] f = new int[n + 1][n + 1];
int mod = (int)1e9 + 7;
for (int i = 0; i <= n;i ++) {
f[i][0] = 1;
}
for (int i = 1;i <= n; i ++) {
for (int j = 1; j <= n;j ++) { // 这里的j的范围要是整个,因为是要选取前i个数去凭凑出这个sum的
f[i][j] = f[i - 1][j] % mod;
if (j - i >= 0) {
f[i][j] = (f[i - 1][j] + f[i][j - i]) % mod;
}
}
}
System.out.println(f[n][n]);
}
}