1、题目描述
一个正整数nn可以表示成若干个正整数之和,形如:n=n1+n2+…+nkn=n1+n2+…+nk,其中n1≥n2≥…≥nk,k≥1n1≥n2≥…≥nk,k≥1。
我们将这样的一种表示称为正整数n的一种划分。
现在给定一个正整数n,请你求出n共有多少种不同的划分方法。
输入格式
共一行,包含一个整数n。
输出格式
共一行,包含一个整数,表示总划分数量。
由于答案可能很大,输出结果请对109+7109+7取模。
数据范围
1≤n≤10001≤n≤1000
输入样例:
5
输出样例:
7
2、分析
可以看成是 完全背包问题,因为每种数字可以选无限次。
/*
完全背包问题:每种数可以选多次(无限次)
f[i][j] = f[i-1][j] + f[i-1][j-i] + f[i-1][j-2*i] + ... + f[i-1][j-k*i]
f[i][j-i] = f[i-1][j-i] + f[i-1][j-2*i] + f[i-1][j-3*i] + ... + f[i-1][j-k*i] + f[i-1][j-(k+1)*i]
==> f[i][j] = f[i-1][j] + f[i][j-i]
*/
3、代码
/*
完全背包问题:每种数可以选多次(无限次)
f[i][j] = f[i-1][j] + f[i-1][j-i] + f[i-1][j-2*i] + ... + f[i-1][j-k*i]
f[i][j-i] = f[i-1][j-i] + f[i-1][j-2*i] + f[i-1][j-3*i] + ... + f[i-1][j-k*i] + f[i-1][j-(k+1)*i]
==> f[i][j] = f[i-1][j] + f[i][j-i]
*/
import java.io.*;
import java.util.*;
public class Main{
static int N = 1010, mod = (int)1e9 + 7;
static int[][] f = new int[N][N];
public static void main(String[] args) {
Scanner in = new Scanner(new InputStreamReader(System.in));
int n = in.nextInt();
//初始化
//f[i][j] 表示所有从前i个数中选总和不超过j的选法的集合
f[0][0] = 1;
for(int i = 1;i <= n;i ++) {
f[i][0] = 1;
for(int j = 0;j <= n;j ++) {
f[i][j] = f[i-1][j] % mod; //不选第i个
if(j >= i) f[i][j] = (f[i][j] + f[i][j-i]) % mod;
}
}
System.out.println(f[n][n]);
}
}