计数类dp
例题:整数划分
一个正整数
我们将这样的一种表示称为正整数
现在给定一个正整数
输入格式
共一行,包含一个整数
输出格式
共一行,包含一个整数,表示总划分数量。
由于答案可能很大,输出结果请对
数据范围
输入样例:
5
输出样例:
7
解法一:完全背包问题
分析:
这个问题可以看成一个完全背包问题,背包的容积是这个数
要计算的是恰好能把体积为
初始化:
求最大价值,当都不选时,价值显然是
而求方案数时,当都不选时,方案数是
即:for (int i = 0; i <= n; i ++) f[i][0] = 1;
当然,f[0][0] = 1
。
压缩到一维后: f[0] = 1
状态计算:
求方案数:把集合选
因此
二维:
#include <iostream>
using namespace std;
const int N = 1010, mod = 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=0;j<=n;j++)
{
if (j < i) f[i][j] = f[i-1][j] % mod;
else f[i][j] = (f[i-1][j] + f[i][j-i]) % mod;
}
}
cout <<f[n][n];
}
一维:
#include <iostream>
using namespace std;
const int N = 1010, mod = 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]) % mod;
}
}
cout <<f[n];
}S
解法二
状态表示:
状态计算:
分成两部分:
- 最小值是
:
去掉一个 ,即是 的方案数、 - 最小值大于
:
让所有数减 ,即是 的方案数。
所以 f[i][j] = f[i-1][j-1] + f[i-j][j]
初始化:
f[0][0] = 1
表示总和为
#include <iostream>
using namespace std;
const int N = 1010, mod = 1e9+7;
int f[N][N];
int main()
{
int n;
cin >>n;
f[0][0] = 1;
for (int i=1;i<=n;i++)
{
for (int j=1;j<=n;j++)
{
if (i >= j) f[i][j] = (f[i-1][j-1] + f[i-j][j]) % mod;
}
}
int sum = 0;
for (int i=0;i<=n;i++) sum = (sum + f[n][i]) % mod;
cout <<sum;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探