计数类DP

计数类DP

1.经典例题——整数划分

一个正整数 n 可以表示成若干个正整数之和,形如:n=n1+n2++nk,其中 n1n2nk,k1

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

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

输入格式

共一行,包含一个整数 n

输出格式

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

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

数据范围

1n1000

输入样例:

5

输出样例:

7

注:本题来源于AcWing题库第900题

2.经典例题思路(1)

其实我们可以把这个题看成完全背包来做。

没学过的去这里

只要我们把 1~n 的这些数都看成可供选择的物品,每个物品的体积、价值都是自己,且有无限件可取。

一个完全背包就出现了。

这还有什么好说的,直接上代码!

3.经典例题代码(1)

就不放注释了吧,代码太短了,只要把完全背包学会就能看明白。

#include<iostream>
using namespace std;
const int N=1005,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];
return 0;
}

4.经典例题思路(2)

我们应该还可以想到一种方案:

f 数组表示所有总和是 i 且恰好能表示成 j 个元素的和的方案。

怎样计算呢?

我们可以把它分成不分去求,一部分最小值是1,一部分大于1,这样就能算出每一个集合了。

最后,在枚举 f[n][i] 加到 ans 数组里,输出,完事。

5.经典例题代码(2)

#include<iostream>
using namespace std;
const int N=1005,mod=1e9+7;
int n,ans;
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;//最小值是1的情况加最小值不是1的情况
for(int i=1;i<=n;i++) ans+=f[n][i];
cout<<ans;
return 0;
}

完~

如果觉得还行,就点个赞吧,您的支持对我来说很重要。

posted @   Rainforests  阅读(51)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
点击右上角即可分享
微信分享提示