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

首先我们来看两道题目:

  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;
}


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

posted @ 2010-09-11 14:48  Sephiroth.L.  阅读(415)  评论(0编辑  收藏  举报