整数划分

来源:互联网 发布:360软件管理 编辑:程序博客网 时间:2024/05/16 14:42

题目描述

经过第一轮的游戏,不少同学将会获得圣诞特别礼物,但这时细心的数学课代表发现了一个问题:留下来的人太多而使礼物数量可能不够,为此,加试了一道数学题:将一个正整数n分解成若干个互不相等的正整数的和,使得这些数的乘积最大,当主持人报出一个n后,请你立即将这个最大值报出来,现请你帮你的好友编一个程序来解决这个问题。

输入格式

输入中只有1个数n(其中1<=n<=1000)。

输出格式

输出中也是一个数,是乘积的最大值。

样例输入

7

样例输出

12


此题时将整数M划分成N个不同整数  使N个整数乘积最大 (Wikioi 2612 / RQNOJ 269 / TYVJ 1260)

首先我们不会分解出1 

将M划分成1和(M-1)  乘积不会比M大

1.对于小于4的数 无法将它划分出乘积大于自身的数 所以就不划分

2.当M=4时 2+2=2*2 我们可以划分也可以不划分 为了方便 将它划分成2+2

3.当M>4时 保证不重复和不分解出1  分解出的数越多越好

   M>4时 可以分解成2个整数乘积大于M

    


为了分解更多的数

1.可以将M分解成2+3+...+k一直到和大于等于M

   若和=M 则此方案为最佳

   否则必须删掉一个数

   当比M大1时 删掉2 并将(k-1)变成k

   当比M大w(w!=1)时 删掉w

2.分解成2+3+...+k<=M使得再加上k+1时大于M

   则对于差w 将w分成w个1  从大到小加到分解的数上

   若w>k-1 则加完一边后再继续从大到小加1

   如分解6

   2+3<6<2+3+4

   2+3+4-6=3

   将3分成3个1

   加到3 2 上 还剩一个1

   再加到4 3中的3上

   由大到小的顺序  是为了保证不相同


代码如下


#include<iostream>#include<cstdio>#include<cstring>using namespace std;int s[11111];int ans[1111];int m,a,b,c,n;void print(int ans[1111]){    int a;    for(a=1000;a>1;a--)    if(ans[a])break;    while(a)    {        cout<<ans[a];        a--;    }}void jinwei(int ans[1111]){    int i;    for(int i=1;i<=1000;i++)    if(ans[i]>=10)    {        ans[i+1]=ans[i+1]+ans[i]/10;        ans[i]%=10;    }}void calc(){    int a,b;    ans[1]=1;    for(a=1;a<=n;a++)    {        for(b=1;b<=500;b++)        ans[b]=ans[b]*s[a];        jinwei(ans);    }}int main(){    cin>>m;    for(a=1;m>s[a-1];a++)    {        s[a]=min(a+1,m);        m-=s[a];        if(m<=s[a])break;    }    n=a;        while(m)    {        for(a=n;a>=1;a--)        {            s[a]++;            m--;            if(m<=0)break;        }    }    calc();    print(ans);    return 0;}


   



对于可相同的整数划分(VIJOS 1033)

将整数M划分成N个整数 使N个整数乘积最大(Wikioi 3179)

将M划分成1和(M-1)  乘积不会比M大  故不分解出1

因此

1.对于小于4的数 无法将它划分出乘积大于自身的数 所以就不划分

2.当M=4时 2+2=2*2 我们可以划分也可以不划分 为了方便 将它划分成2+2

3.当M>4时 可证明M分解成若干整数的和 他们的积大于M

   考虑分解成2个数的情况

   当M为偶数时  (M/2)^2>M 解得M>4

   当M为奇数时  ((M+1)/2)*((M-1)/2)>M 解得M>2*5^(1/2)

   因此M>4时 可以分解成2个整数乘积大于M 需要将它分解

   M>4时 令M=x+(M-x)

   考虑y=x*(M-x)  y表示数乘积比M大的值

   y为二次函数 开口向下  在M/2时取到最大值 在(0,M/2)单调递增 在(M/2,M)单调递减

   所以M为偶数时 分解成M/2+M/2

   M为奇数时 分解成(M+1)/2+(M-1)/2

   然后对分解后的数也尝试考虑1.2.3


这样做后 发现最后分解的数都为2和3

由于2*2*2<3*3而2+2+2=3+3

所以每分解成3个2 我们将它变成2个3

这样就可以求出最大的乘积  


#include<iostream>#include<cstdio>using namespace std;int m,a,b,z[1011];void print(){    int a;    for(a=1000;a>1;a--)if(z[a])break;    while(a)    {        cout<<z[a];a--;    }    cout<<'\n';}void jinwei(){    for(int a=1;a<=1000;a++)    if(z[a]>=10)    {        z[a+1]=z[a+1]+z[a]/10;        z[a]%=10;    }}void calc(){    z[1]=1;    while(b)    {        z[1]*=2;        b--;    }    while(a)    {        for(int k=1;k<=1000;k++)z[k]*=3;        jinwei();        a--;    }    print();}int main(){    cin>>m;    if(m<=4)    {        cout<<m<<'\n';        return 0;    }    while(m%3!=0)    {        b++;        m-=2;    }    a=m/3;    calc();    return 0;}


原创粉丝点击