计数类DP——整数划分
//背包:容量是n的背包,n个物品的体积分别是1,2,3……n,恰好装满背包的方案数,每个物品可以用无限次
状态表示:f(i, j)
集合:从1~i中选,体积恰好是j的方案
属性:数量
状态计算:
f(i,j):i选了0,1,2,3……n个: f[i - 1][j], f[i-1][j-i], f(i-2, j - 2i), f(i-1,j-si)
从1~i中选,选了2个i,并且和恰好为j
从1~i-1中选,和为j - 2r
……
f[i][j] = f[i-1][j] + f[i-1][j-i] + f[i-1][j-2i] + …… +f[i-1][j-i*s]
f[i][j-i] = f[i-1][j-i] + f[i-1][j-2i] +……+ f[i-1][j-i*s]
——> f[j] = f[j] + f[j-i]
#include <iostream> #include <algorithm> using namespace std; const int N = 1010, mod = 1e9 + 7; int n, 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; }
第二种解法:
所有总和是i,并且可以恰好表示成j个数的和的方案
f(i, j)
方案中最小值是1 : 把最小值1去掉就是f[i-1][j-1]
方案中最小值大于1: 把每个数都减去1:f[i-j, j]
f[i][j] = f[i-1][j-1] + f[i-j,j]
ans = f[n][1] + f[n][2]……f[n][n]
完全背包的状态转移方程是:f[i][j] = f[i-1][j] + f[i][j-i]
#include <iostream> #include <algorithm> using namespace std; const int N = 1010, mod = 1e9 + 7; int n, 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 ans = 0; for(int i = 1;i <= n;i++) ans = (ans + f[n][i]) % mod; cout<<ans<<endl; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?