整数划分问题(分治算法经典)

本文详细解析了整数划分问题的递归解决方案,并提供了C++和Java代码实例。重点介绍了q(n,m)的递归关系,展示了如何通过分治策略求解正整数n的划分数p(n)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

整数划分问题是将一个正整数n拆成一组数连加并等于n的形式,且这组数中的最大加数不大于n。
即:n=n1+n2+…+nk;
n1>=n2>=n3…>=nk
如整数的6划分为:
6
5 + 1
4 + 2, 4 + 1 + 1
3 + 3, 3 + 2 + 1, 3 + 1 + 1 + 1
2 + 2 + 2, 2 + 2 + 1 + 1, 2 + 1 + 1 + 1 + 1
1 + 1 + 1 + 1 + 1 + 1共11种。

补充:正整数的这种操作称为正整数的划分,正整数的不同划分个数称为正整数n的划分数,记为p(n)。例如:p(6)=11;

解题:

分析:在如上对6的划分中,我们可以发现分层进行。将最大加数不超过m的划分个数记作q(n,m).
p(6)=q(6,6)
对q(n,m),我们可以建立如下递归关系。
(1).q(n,1)=1,n>=1;
即n只能划分为1+1+…+1(n个1️⃣)
(2).q(n,m)=q(n,n),m>=n;
最大加数m永远不能大于n。
(3)q(n,n)=1+q(n,n-1)。
当取n1=n时,只有一种划分,当n1=n-1时,有q(n,n-1)种划分
(4):q(n,m)=q(n,n-1)+q(n-m,m),n>m>1.
(正整数n的最大加数n1不大于m的划分)即q(n,m)由n1=m的划分(这里可看做q(n-m,m),因为第一个数确定为m,剩下数的总和为n-m,对其在拆分即可)和n1<=m-1的划分组成。

综上:得到q(n,m)的递归式

q(n,m)={1,n=1,m=1;
------------q(n,n),n<m;
------------q(n,n-1)+1,n=m
------------q(n,m-1)+q(n-m,m),n>m>1}

代码实现:C++

#include<iostream>
using namespace std;
int q(int n,int m) {
    if ((n < 1) || (m < 1))return 0;
    if ((n == 1) || (m == 1))return 1;
    if (n < m)return q(n, n);
    if (n == m)return q(n, m - 1) + 1;
    return q(n, m - 1) + q(n - m, m);
}
int main() {
    int n;
    cin >> n;
    cout << q(n, n) << endl;
    return 0;
}

代码实现,JAVA:

public static int q(int n,int m){
if ((n < 1) || (m < 1))return 0;
    if ((n == 1) || (m == 1))return 1;
    if (n < m)return q(n, n);
    if (n == m)return q(n, m - 1) + 1;
    return q(n, m - 1) + q(n - m, m);
    }

效果:
在这里插入图片描述
总结:这是最经典的分治之一,反复应用分治手段,可以使子问题和原问题类型一致而规模不断缩小,最终使得子问题很容易求解,最后合并所得解即可。本题中,通过对q(n,n)的分解,我们得到若干个简单的子问题q(6,1)、q(1,5)等等,最终合并得p(n).

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

0<Solving)1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值