分析1
根据题意这道题是在求组合,不考虑顺序的
这道题可以转化为一个完全背包问题,背包容量是n,有n种物品,这些物品的权重是1~n,每种物品可以取无限次。这不就是之前做过的完全背包问题吗!
完全背包问题中统计的是总价值的最大值,这道题是计数,我们只需要将原来的状态方程中的取最大值操作更改成累加操作,就可以求出所有的方案数
这道题也可以用类似于完全背包的方式进行优化,详细的过程在背包问题的博客中已经有了(我懒的写了),我们可以用类似的方式将二维的优化成一维的
代码1
#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]+f[j-i])%MOD;
cout<<f[n]<<endl;
return 0;
}
分析2
f[i][j]表示总和是i且恰好表示成j个数的和的方案数
对于f[i][j]的状态计算可以将这个状态分成两类
1、方案中最小值是1,f[i-1][j-1]即总和减去1,所需要的数也减少一个
2、方案中最小值大于1,f[i-j][j]即所有所有数都减去1,所需要的数的个数不变
代码2
#include <bits/stdc++.h>
using namespace std;
const int N=1010,MOD=1e9+7;
int n;
int f[N][N];
int main()
{
cin>>n;
f[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=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<<endl;
return 0;
}