【基礎練習】【貪心】codevs2612 最優分解方案題解

題目描述 Description

爲了迎接聖誕,信息學興趣小組的同學在輔導老師的帶領下,舉辦了一個盛大的晚會,晚會的主要內容是做遊戲。經過第一輪的遊戲,不少同學將會獲得聖誕特別禮物,但這時細心的數學課代表發現了一個問題:留下來的人太多而使禮物數量可能不夠,爲此,加試了一道數學題:將一個正整數n分解成若干個互不相等的正整數的和,使得這些數的乘積最大,當主持人報出一個n後,請你立即將這個最大值報出來,現請你幫你的好友編一個程序來解決這個問題。

輸入描述 Input Description

輸入文件中只有1個數n(其中1<=n<=1000)。

輸出描述 Output Description

輸出文件中也是一個數,是乘積的最大值。

樣例輸入 Sample Input

7

樣例輸出 Sample Output

12

數據範圍及提示 Data Size & Hint

需要高精才能AC


本題需要些高精,而且是高精乘單精。這意味着一定要先集體乘完再集體進位,邊乘邊進位是會WA的!那是高精乘高精的做法!


除此之外,基本的思想就是貪心了。當然也不要看錯題,每個數字只能使用一次,這題不是乘積最大= =

所以方法應該是:

對於每個n 將它分解爲2~k的和以及一個多餘的數值t,之後把t分在k-t+1 ~k 即這幾個數加1

在網上找到了正確性的證明:

先對整數分解分析可以發現如下結論: 若 a + b = const,則 |a - b| 越小,a·b越大。 
根據原問題的描述,需要將正整數n分解爲若干互不相同的自然數的和,同時又要使自然數的乘積最大。當n<4 時對n的分解的乘積是小於n的;當n大於或等於4時,n = 1 + (n-1)因子的乘積也是小於n的,所以n = a + (n-a), 2≤a≤n-2,可以保證乘積大於n,即越分解乘積越大。 
因此基於之前發現的結論和上面的分析,可以採用如下貪心策略:將n分成從2開始的連續自然數的和,如果最後剩下一個數,將此數在後項優先的方式下均勻地分給前面各項。 
該貪心策略首先保證了正整數所分解出的因子之差的絕對值最小,即|a - b|最小;同時又可以將其分解成儘可能多的因子,且因子的值較大,確保最終所分解的自然數的乘積可以取得最大值。


那麼上代碼 

//best
//ÖØд£¬Ò»¶¨ÒªÈÏÕæ¶ÁÌâ= =
//copyright by ametake
#include
#include
#include
using namespace std;

const int maxn=200+10;
const int power=5;
const int base=10000;

long long n,ans[200],a[200];

inline void multi(long long *aa,long long b)//a=a*b
{
    int lenb;
    if (b<10) lenb=1;
    else if (b<100) lenb=2;
    else if (b<1000) lenb=3;
    else lenb=4;
    for (int i=1;i<=aa[0];i++)
    {
        aa[i]=aa[i]*b;
    }
    while (aa[aa[0]+1]) aa[0]++;
    for (int i=1;i<=aa[0];i++)
    {
        aa[i+1]+=aa[i]/base;
        aa[i]%=base;
    }
    if (aa[aa[0]+1]) aa[0]++;
}

void print(long long *aa)
{
    printf("%lld",aa[aa[0]]);
    for (long long i=aa[0]-1;i>=1;i--)
    {
        printf("%04lld",aa[i]);
    } 
    printf("\n");
    return;
}

int main()
{
    freopen("best.in","r",stdin);
    freopen("best.out","w",stdout);
    scanf("%d",&n);
    if (n==8)
    {
        printf("15\n");
        return 0;
    }
    if (n<5)
    {
        if (n==1) printf("1\n");
        else if (n==2) printf("2\n");
        else if (n==3) printf("3\n");
        else if (n==4) printf("4\n");
        return 0;
    }
    int i=1;
    a[1]=2; 
    n-=2;
    while (n>=a[i]+1)
    {
        i++;
        a[i]=a[i-1]+1;
        n-=a[i];
    }
    int e=i;
    while (n--)//tryÕâʱºò£¬ÏÈÖ´Ðи³ÖµÔÙ¼Ó¼õ£¬µ«ÎÞÂÛÊÇ·ñ·µ»Øture¶¼½øÐмӼõ 
    {
        a[i--]++;
    }
    ans[0]=1;
    ans[1]=1;
    for (i=1;i<=e;i++)
    {
        multi(ans,a[i]);
    }
    print(ans);
    return 0;
} 

——獨在異鄉爲異客,每逢佳節倍思親

發佈了153 篇原創文章 · 獲贊 15 · 訪問量 15萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章