题目
一个正整数 nn 可以表示成若干个正整数之和,形如:n=n1+n2+…+nkn=n1+n2+…+nk,其中 n1≥n2≥…≥nk,k≥1n1≥n2≥…≥nk,k≥1。
我们将这样的一种表示称为正整数 nn 的一种划分。
现在给定一个正整数 nn,请你求出 nn 共有多少种不同的划分方法。
输入格式
共一行,包含一个整数 nn。
输出格式
共一行,包含一个整数,表示总划分数量。
由于答案可能很大,输出结果请对 1e9+7 取模。
数据范围
1≤n≤10001≤n≤1000
输入样例:
5输出样例:
7
思路 (完全背包计数)
和完全背包类似,\(dp[i][j]\)可以由\(dp[i - 1][j]\)和\(dp[i][j - v[i]] + w[i]\)递推而来,这里的\(v[i] = 1\),由于\(dp[i][j]\)表示考虑前\(i\)个物品,当背包容量为\(j\)时的方案数
因此dp方程可以写为
\(dp[i][j] = dp[i - 1][j] + dp[i][j - 1]\)
初始化:
\(dp[0][i] = 1\)
Code
#include <iostream>
using namespace std;
const int mod = 1e9 + 7;
int dp[1000];
// 完全背包计数问题
// dp[i][j] 表示考虑前i个物品, 当背包容量为j时的方案数
// dp[i][0] = 1;
// dp[i][1] = 1;
// dp[i][j] = dp[i - 1][j] + dp[i][j - i];
// dp[1][2] = 1
// dp[2][2] = 2 = dp[1][2] + dp[1][1]
// dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - v[i]] + w[i])
// dp[j] = dp[j] + dp[j - v[i]]
int main() {
dp[0] = 1;
for(int i = 1; i <= 1000; i ++) {
for(int j = i; j <= 1000; j ++) {
dp[j] = (dp[j] % mod + dp[j - i] % mod) % mod;
}
}
int n;
cin >> n;
cout << dp[n];
}
浙公网安备 33010602011771号