给定一个正整数n,将其分成m段,每段为n1,n2,...,nm,求怎么划分使得n1*n2*...*nm最大

该博客探讨了如何将一个正整数N分解为n个自然数之和,以求得这n个数乘积的最大值。通过动态规划的方法,分析最优解的结构并给出递归定义,然后提供源代码实现自底向上的计算过程,以找到和为N时乘积最大值的分解方式。

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

题目:自然数N分解为n个自然数的和,求这n个数的乘积最大值

分析:最优问题,可以用动态规划求解
1、描述最优解结构
    N = a1 + a2 + ... + an;
    M = a1 * a2 * ... * an;
求M的最大值
    考虑到N = a + b,而a与b又可以分解为另外几个和为a或b的数的积,因此对于确定的N = a + b,有一个最优解M(N) = M(a)*M(N-a)。而a又有1到N/2种取值,所以有一般最优解M(N) = max{M(a) + M(N - a)}(a < N/2)。而对于1、2、3、4、5等的M值列一个表,就可以得到N<=4时,M(N) = N。于是有下列递归定义。
2、递归定义最优解

   动态规划求解:一个数分解为n个数的和,求n个数积最大 - 埋香 - 低眉浅谈
 
3、按自底向上的方式计算最优解
源码:
#include <iostream>
#include <fstream>
#include <math.h>

using namespace std;

#define SIZE 1000

unsigned long m[SIZE], t[SIZE];  
//m[i]存放和为i的数的乘积最大值,t[i]存放使m[i]为最大时,将i划分为2部分的j的值,即m[i]=m[j]*m[i-j]最大时j的值

void mt(int a)
{
	int i, j;
	for (i = 0; i < SIZE; i++)   //m、t初始化
	{
		m[i] = i;
		t[i] = i;
	}
	for (i = 4; i <= a; i++)         //按自底向上来得到m与t的值
	{
		for (j = 2; j <= i/2; j++)
		{
			if (m[i]  <= m[j] * m[i - j])
			{
				m[i] = m[j] * m[i - j];
				t[i] = j;
			}
		}	
	}
}

void printt(int a)       //打印和为a,积最大的所有数
{
	int k;
	k = t[a];             //k为a的第一次分解值
	if (k == t[k])      //不能再分的时候,输出k
	{
		cout<<k;		
	}
	else            //继续分解,打印出和为k,积最大的所有数
	{
		printt(k);
	} 

	if(a - k > 0)        //打印出和为a - k,积最大的所有数
	{ 
		cout<<" * ";
		printt(a - k);
	}
}

void main()
{
	int n;
	cout<<"input a number(<= 62) ";    //输入小于62的数。由于unsigned long只能表示到2的31次方,只能存储小于62的M值
	cin>>n;
	mt(n);                        //计算m和t
	cout<<m[n]<<" = ";
	printt(n);                        //打印
	cout<<endl;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值