整数划分问题详解:一个递归算法的诞生与优化
创作时间:
2025-01-22 04:24:29
作者:
@小白创作中心
整数划分问题详解:一个递归算法的诞生与优化
整数划分问题是组合数学中的一个经典问题,具有广泛的应用场景,如计算机科学、密码学等。本文将深入探讨整数划分问题的递归求解方法,并给出具体的代码实现。
问题定义与记号引入
我们首先引入记号q(n,m),表示在正整数n的所有不同划分中,最大加数n1不大于m(即n1≤m)的划分个数。本题要求的p(n),实际上就是q(n,n)。
递推式的推导
分析整数6的11种不同划分的构成,可以得到一个最重要的递推式子:当1<m<n时,q(n,m)=q(n-m,m)+q(n,m-1)。如下图所示。
当n=6,m=3时,有:q(6,3)=q(6-3,3)+q(6,2),q(6,3)表示最大加数不超过3的划分数,即虚线以下3行包括的划分,其中第一行是3开头的划分,个数是q(6-3,3),即从6中扣除3,剩下的值(即3)的最大加数不超过3的划分,后两行是q(6,2),表示最大加数不超过2的划分数
再补充一些边界情形,就可以建立q(n,m)的递归关系(n,m均为≥1的整数):
- 当n=1或m=1时,q(n,m)=1
- 当最大加数n1不大于m=1时,任何正整数n只有一种划分形式,即n=1+1+…+1
- 而当n=1时,也只有一种划分形式,即n=1
- 当m>n时,q(n,m)=q(n,n)
- 最大加数n1实际上不能大于n,因此当m>n时,q(n,m)=q(n,n)
- 当n=m时,q(n,m)=q(n,n)=1+q(n,n-1)
- 正整数n的划分由n1=n的划分(只有1种划分,就是n本身)和n1≤n-1的划分组成。
- 当n>m>1时,q(n,m)=q(n,m-1)+q(n-m,m)
- 正整数n的最大加数n1不大于m的划分(个数为q(n,m),由n1=m的划分(个数为q(n-m,m)和n1≤m-1的划分(个数为q(n,m-1)组成
因此,可以得到下式所示的递推关系。这个递推式子很容易转换成一个递归函数,从而本题可以用递归方法求解。
初始递归代码实现
#include<iostream>
using namespace std;
long long q(int n, int m){
if(n<1 || m<1) return 0;
else if(n==1 || m==1) return 1;
else if(m>n) return q(n, n);
else if(n==m) return (q(n, n-1)+1);
else return (q(n, m-1)+q(n-m, m));
}
int main()
{
int n;
while(cin >> n)
cout << q(n,n) << endl;
return 0;
}
代码优化
由于初始递归代码在大数据时会运行超时,因此需要进行优化。引入二维数组record,record[n][m]记录求得的q(n,m)。
#include<iostream>
using namespace std;
long long record[401][401]; //全局变量,编译器将各元素值初始化为0
long long q(int n, int m){
if(record[n][m]) return record[n][m];
if(n<1 || m<1) return record[n][m]=0;
else if(n==1 || m==1) return record[n][m]=1;
else if(m>n) return record[n][m]=q(n, n);
else if(n==m) return record[n][m]=(q(n, n-1)+1);
else return record[n][m]=(q(n, m-1)+q(n-m, m));
}
int main()
{
int i, j, n;
for(i=1;i<=400;i++){ //求出所有的q(n,m)
for(j=1;j<=i;j++) record[i][j] = q(i,j);
}
while(cin >> n)
cout << q(n,n) << endl;
return 0;
}
在优化后的代码中:
- 定义了一个二维数组record,record[n][m]记录求得的q(n,m)
- 在递归函数q里,增加了一条语句:当record[n][m]的值非0,意味着已经求出了record[n][m],则不递归求解,而是直接返回其值
- 每个条件分支里都是先对record[n][m]赋值,再返回record[n][m]的值
- 在main函数里,用一个二重循环求出所有的q(n,m),m≤n≤400,即只求出二维数组record主对角线及以下元素的值
- 最后,对输入的每个n值,答案p(n)=q(n,n)=record[n][n]直接输出即可
下图给出了求得的record数组部分元素的值,根据这些值,也可以验证上述递推式子。需要说明的是,在record数组里,包含了整数1~400的划分数(对角线上的值)。
热门推荐
SOGC指南:胎儿生长受限-单胎妊娠的筛查、诊断和管理
知识付费行业分析报告
投资者在加密货币骗局中损失31万美元
板块构造学说:支持地球表面板块运动的科学理论
挤压了正常通勤,代表建议调整老人免费乘公交,内蒙古包头回应
西安钟楼:穿越六百年的古都地标
揭秘:如何制作老豆腐脑!传统风味,味蕾新体验
别再傻傻分不清!“高频”出现的 5 种高速路标线,助你安全畅行
映山红——生命之美(花开花落)
比特币网络费用7天内下降30%,矿工收入却增长4%
员工突然离职拒不归还财物?HR必知的5大应对策略与法律风险解析
三维仿真医护软件系统:医学教育的创新与发展
健康守护,防“艾”同行——艾滋病防治宣传教育知识
比特币再次突破10万美元大关,特朗普关税政策调整将持续影响市场动向
转型与向“新”: 金融促进县域产业质效提升的内江实践
李姓的传说:从神树救难到姓氏的由来
肚子疼时喝热水真的有用吗?医生这样说
梦见变成丧尸的深层含义:从梦境解析到自我成长
绿豆怎么种发芽最快:从选豆到催芽的完整指南
手链长了怎样截短?多种实用解决方案帮你轻松应对
揭秘暗恋信号:8大迹象揭示你正被暗恋!
四季豆生产过程中的追肥时机与方法
必看!跨境电商税务合规秘籍之 OSS 与 IOSS
糖尿病人正确减肥,要牢记这7点,不然血糖很难降下去
VR虚拟展馆展厅研究现状和背景趋势分析报告
老房子按什么标准评估
2025年二手房买卖常见陷阱与防范指南!这些坑千万不要踩!
全民“补钙”怎么补?最新指南分人群给出精准指导
7种有效改善睡眠的方法,不妨尝试
腐竹是什么材料做的