两个整数划分——一句话造成完全不同的算法

首先我们来看两道题目:

  1. 将一个整数n分成若干个互不相同的数的和,使得这些数的乘积最大。其中1<=n<=1000。
  2. 若干个正整数之和为n,其中:n<2000,试求它们乘积的最大值以及该最大值的位数k。
很容易看出来,两道题目的区别就在于第一道题目要求各个数不同。
我们来看看4~10这几个数分解的方法,这个可以手工进行计算得出:
  • 4 2*2
  • 5 2*3
  • 6 2*4
  • 7 3*4
  • 8 3*5
  • 9 2*3*4
  • 20 2*3*5
大家在做中学的物理题的时候,应该都知道两个和相等的数,相差越小乘积越大。那么很容易想到这个也是相差越小,乘积越大。那么我们要做的就是将n分为互不相同的几分,要求相差最小。
我们的做法就是,从2开始,每个数是前面的数+1。直到无法满足为止,然后在将剩下的数从后向前给每个数分1。比如说8,第一步我们分为2,3,剩下3,然后从后向前给每个数分1,变成3,4,剩下1,然后重复分1的过程,得到最终结果3,5。
整数分解1
    
      
#include < stdio.h >
#define maxn 10000

int a[maxn];
int n,tot;
long long ans;

int main()
{
freopen(
" fen1.in " , " r " ,stdin);
freopen(
" fen1.out " , " w " ,stdout);

scanf(
" %d " , & n);
a[
0 ] = 1 ;
while (n > a[tot])
{
++ tot;
a[tot]
= a[tot - 1 ] + 1 ;
n
-= a[tot];
}
while (n)
for ( int i = tot;i > 0 ; -- i)
{
if ( ! n) break ;
++ a[i];
-- n;
}
for ( int i = 1 ;i < tot; ++ i) printf( " %d " ,a[i]);
printf(
" %d\n " ,a[tot]);
ans
= 1 ;
for ( int i = 1 ;i <= tot; ++ i) ans *= a[i];
printf(
" %lld\n " ,ans);
return 0 ;
}

 

然后看第二题。
根据数学规律可知,若要使和固定的数的乘积最大,必须使这些数尽可能的多为3,于是可推得以下规律:
当N mod 3=1 时,N可分解为一个4和若干个3的和;  
当N mod 3=2 时,N 可分解为一个2和若干个3的和;
当N mod 3=0 时,N 直接分解为若干个3的和。
按照这一分解方法,所有因数的乘积必定最大。
整数分解2
    
      
#include < stdio.h >

long long ans;
int n;

int main()
{
freopen(
" fen2.in " , " r " ,stdin);
freopen(
" fen2.out " , " w " ,stdout);

ans
= 1 ;
scanf(
" %d " , & n);
if (n % 3 == 0 )
while (n)
{
ans
*= 3 ;
n
-= 3 ;
}
else if (n % 3 == 1 )
{
ans
= 4 ;
n
-= 4 ;
while (n)
{
ans
*= 3 ;
n
-= 3 ;
}
}
else
{
ans
= 2 ;
n
-= 2 ;
while (n)
{
ans
*= 3 ;
n
-= 3 ;
}
}
printf(
" %lld\n " ,ans);
return 0 ;
}


两道题目看似相同,但是一个条件的限制使得两道题目的算法完全不同。认真审题,永远是第一步。

你可能感兴趣的:(算法)