完全背包解法
重点
1. 状态表示:f[i][j] 表示从前i个数里选,总和恰巧为j的方案的集合,属性是数量
2. 集合划分:f[i][j] = f[i - 1][j] + f[i - 1][j - i] + f[i - 1][j - 2i] + … + f[i - 1][j - ki]
f[i][j] = f[i - 1][j] + f[i][j - i]
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010, mod = 1e9 + 7;
int n;
int f[N];
int main() {
cin >> n;
f[0] = 1;
for (int i = 1; i <= n; i++) {
for (int j = i; j <= n; j++) {
f[j] = ((long long)f[j] + f[j - i]) % mod;
}
}
cout << f[n] << endl;
return 0;
}
另一种不同的dp表示
重点 *
1. 状态表示:f[i][j] 表示和为i用j个数表示的所有方案的集合,属性个数
2. 集合划分:f[i][j] = f[i - 1][j] + f[i - j][j]
f[i - 1][j]表示最小的一个数为1的所有的集合
f[i - j][j] 表示最小的一个数不是1的所有的集合,
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1010, mod = 1e9 + 7;
int n;
int f[N][N];
int main() {
cin >> n;
f[0][0] = 1; //和为0用0个数表示,方案数为1
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= i; j++) {
f[i][j] = ((long long)f[i - 1][j - 1] + f[i - j][j]) % mod;
}
}
int res = 0;
for (int i = 1; i <= n; i++) res = ((long long)f[n][i] + res) % mod;
cout << res << endl;
return 0;
}