完全背包问题
将整数划分视为 n 个 物品 每个物品的体积和价值均为 n , 有无限中选法
#include <bits/stdc++.h>
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] += f[j - i];
f[j] %= mod;
}
}
cout << f[n];
return 0;
}
将整数以 1 为界限进行划分, 分为最小值等于 1 和 大于 1 的情况。
#include <bits/stdc++.h>
using namespace std;
const int N = 1010, mod = 1e9 + 7;
int n;
int f[N][N];
int main() {
cin >> n;
// 用 1 个数 划分为总和为 1 的方案数 = 1
f[1][1] = 1;
for (int i = 2; i <= n; i ++ ) {
for (int j = 1; j <= i; j ++ ) {
// 分为最小值是 1, 和最小值大于 1 的情况。
// j 的循环严格控制了 i >= j;
f[i][j] = (f[i - 1][j - 1] + f[i - j][j]) % mod;
}
}
int res = 0;
for (int i = 1; i <= n; i ++ ) res = (res + f[n][i]) % mod;
cout << res ;
return 0;
}
扩展 : 鸣人的影分身
#include <bits/stdc++.h>
using namespace std;
const int N = 30;
int f[N][N];
int n, m, T;
int main() {
cin >> T;
while ( T -- ) {
cin >> m >> n;
memset (f, 0, sizeof f);
f[0][0] = 1;
for (int i = 0; i <= m; i ++ ) {
for (int j = 1; j <= n; j ++ ) {
f[i][j] = f[i][j - 1];
// 这里的判断条件保证了至少能都满足每个数都大于零
if (i >= j) f[i][j] += f[i - j][j];
}
// for (int j = 1; j <= n; j ++ ) {
// cout << f[i][j] << " ";
// }
// cout << endl;
}
cout << f[m][n] << endl;
}
return 0;
}