背包问题刷题

Tomfng Lv1

整数划分

一个正整数 n 可以表示成若干个正整数之和,形如:n=n1+n2+…+nk,其中 n1≥n2≥…≥nk,k≥1。

我们将这样的一种表示称为正整数 n 的一种划分。

现在给定一个正整数 n,请你求出 n 共有多少种不同的划分方法。

输入格式

共一行,包含一个整数 n。

输出格式

共一行,包含一个整数,表示总划分数量。

由于答案可能很大,输出结果请对 109+7 取模。

分析:用f[i][j]来表示状态,即用前i个数,刚好凑出j的所有情况,很明显每一个数的个数是不限量的,所以这是一个完全背包问题。我们要求的属性就是个数

直接用完全背包的状态转移,就是要么不选要么至少选一个f[i,j]=f[i-1,j]+f[i,j-i]

代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<iostream>
using namespace std;
const int N=1010,M=1e9+7;
int f[N][N];
int main()
{
int n;cin>>n;
for(int i=0;i<=n;i++)f[i][0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++){
f[i][j]=f[i-1][j];
if(j>=i)f[i][j]=(f[i][j]+f[i][j-i])%M;
}
cout<<f[n][n];
}

这里注意一下初始化,在求状态的时候要求所有状态都要已知,所以这里会涉及到的f[i][0]要初始化

和完全背包一样的优化思路,将二维变成一维

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include<iostream>
using namespace std;
const int N=1010,M=1e9+7;
int f[N];
int main()
{
int n;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])%M;
}
cout<<f[n];
}
  • 标题: 背包问题刷题
  • 作者: Tomfng
  • 创建于 : 2025-07-24 17:23:00
  • 更新于 : 2025-07-24 17:42:02
  • 链接: https://redefine.ohevan.com/2025/07/24/算法刷题/背包问题刷题/
  • 版权声明: 本文章采用 CC BY-NC-SA 4.0 进行许可。
评论
目录
背包问题刷题