计数类DP
1.经典例题——整数划分
一个正整数 n 可以表示成若干个正整数之和,形如:\(n=n_1+n_2+…+n_k\),其中 \(n_1≥n_2≥…≥n_k,k≥1\)。
我们将这样的一种表示称为正整数 \(n\) 的一种划分。
现在给定一个正整数 \(n\),请你求出 \(n\) 共有多少种不同的划分方法。
输入格式
共一行,包含一个整数 \(n\)。
输出格式
共一行,包含一个整数,表示总划分数量。
由于答案可能很大,输出结果请对 \(10^9+7\) 取模。
数据范围
\(1≤n≤1000\)
输入样例:
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;
}
完~
如果觉得还行,就点个赞吧,您的支持对我来说很重要。
标签:输出,正整数,int,代码,计数,经典,例题,DP 来源: https://www.cnblogs.com/XiaoHei666/p/ji-shu-lei-dp-class.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。