1,题目描述
问题分设 n 是一个正整数。现在要求将 n 分解为若干个互不相同的自然数的和,且使这些自然数的乘积最大。
2,题目分析
对于给定的正整数 n,编程计算最优分解方案。
数据输入:第 1 行是正整数 n。
结果输出:将计算的最大乘积输出到屏幕。
input:10
output:30
10=2+3+5;
30=235;
这道题最开始我的想法是分成两个中间值,就像周长固定,面积想要取最大那类问题一样。但是这个题明确说明了可以分成多个数,所以我的那种想法就不适用了。
然后我在网上看到了其他博主的解法,妙啊~
接下来我将分享一下思路。
- 将n分成从2开始的连续自然数的和,如果最后剩下一个数,将此数在后项优先的方式下均匀地分给前面各项。
- 该贪心策略首先保证了正整数所分解出的因子之差的绝对值最小,即|a - b|最小;同时又可以将其分解成尽可能多的因子,且因子的值较大,确保最终所分解的自然数的乘积值。
举个例子:n=21
从2开始分,依次分成2,3,4,5,6还剩下1不够分了,就把这个1加到2上,最后分成「3,3,4,5,6」
也就是把剩下的不够分的加到了第一个因子上,如果剩下的很多,就依次分给从前到后的因子。
3,代码实现
int Best_div(int n)
{
int i,j,mul=1;
int num;
//初始化一个数组,用来存放分解后的每个数
int a[MAX] = {0};
a[0]=2;
num=n-2;
//利用for循环来从2开始递增,每次后一个数比前一个数大1
//当最后剩下的数小于前一个数时跳出循环
for(i=0;num>a[i];i++)
{
a[i+1]=a[i]+1;
num-=a[i+1];
}
//得到当前数的个数
j=i+1;
//当剩下的数不为0时,均匀分配给前面的数
while(num!=0)
{
a[i]++;
num-=1;
//循环分配
i=(i-1+j)%j;
}
for(i=0;i<j;i++)
mul*=a[i];
cout<<mul;
}
void main()
{
int n;
cin>>n;
cout<<Best_div(n);
}