状态表示:f[i][j]表示从1~i中选,总体积恰好是j的选法的数量
状态计算:对应集合的划分,根据第i个物品选择了几个来划分
f[i][j] 表示前i个整数(1,2…,i)恰好拼成j的方案数
求方案数:把集合选0个i,1个i,2个i,…全部加起来
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];(这一步类似完全背包的推导)
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1010, mod = 1e9 + 7;
int f[N][N];
int n;
int main()
{
cin >> n;
for (int i = 0; i <= n; ++ i) f[i][0] = 1;
for (int i = 1; i <= n; ++ i)
{
for (int j = 0; j <= n; ++ j)
{
f[i][j] = f[i - 1][j];
if (j >= i) f[i][j] = (f[i - 1][j] + f[i][j - i]) % mod;
}
}
cout << f[n][n] << endl;
return 0;
}