• 【a602】最大乘积


    Time Limit: 1 second
    Memory Limit: 32 MB

    【问题描述】

    一个正整数一般可以分为几个互不相同的自然数的,如3=1+2,4=1+3,5=1+4=2+3,6=1+5=2+4,…。
    现在你的任务是将指定的正整数n分解成若干个互不相同的自然数的和,且使这些自然数的乘积最大。
    

    【输入格式】

    仅一行,正整数n(3≤n≤10000)。
    

    【输出格式】

    共两行。第一行是分解方案,相邻的数之间用一个空格分开,并且按从小到大的顺序。第二行是最大的乘积。
    

    【输入样例】

    10
    

    【输出样例】

    2 3 5
    30
    

    【题目链接】:http://noi.qz5z.com/viewtask.asp?id=a602

    【题解】

    注意这里是说分解成若干个不同的;不能有相同的;
    首先考虑分解后的情况.
    假设一个数字为h;
    分解成两个部分a,h-a;
    然后考虑它们的乘积与h的大小关系
    令f(a)=a*(h-a)-h
    =a*h-a*a-h
    =(a-1)*h-a*a
    这里让a< h/2(因为要不同嘛,就假设a< h-a呗->a< h/2)
    则h>2*a
    则f(a)>(a-1)*2a-a*a
    ->f(a)>a*a-2*a;
    ->f(a)>a(a-2);
    也就是说如果a>=2的话
    f(a)>a(a-2)>=0
    即f(a)>0
    也即a*(h-a)>h
    所以如果分成的若干个不同的数,它们都大于1的话,那么分成的乘积肯定比原来的大;
    这里;再展示一个事实;
    设h=2*s
    假设他分成了
    s-1和s+1
    那么乘积为s^2-1
    如果分成了
    s-2和s+2
    那么乘积为s^2-4
    也就是说分成的两个数a,b
    它们的差的绝对值越小;
    它们的乘积就相应地越大;
    这样我们可以先选取连续的自然数
    2,3,4,5….x
    这里(2+x)*(x-1)/2<=n
    然后令temp = n-(2+x)*(x-1)/2
    如果tmep=0
    那么因为是连续的自然数,那么它们的差肯定是最小的;(差都是1);
    则直接输出2,3,4..x就好
    如果temp>0;
    那么就把temp平均地分配到前面的数字里面去;
    当然你要从后往前一个一个地分配
    比如
    n=13
    2 3 4
    13-(2+3+4)=4
    则分配两个1给4,然后2和3分别给它们分配一个1(在平均的情况下尽量先分配后面的)
    ->3 4 5
    这样就能保证差的绝对值相对地小;
    最后的成绩也就越大;
    (在数学推导上的贪心?)
    最后数字很大要写个高精度乘单精度;
    (n=3和4的情况特判一下)

    【完整代码】

    #include <cstdio>
    #include <iostream>
    #include <vector>
    using namespace std;
    #define pb push_back
    #define LL long long
    
    const int MAXN = 100;
    
    int n,now;
    LL a[1000];
    vector <LL> v;
    
    int main()
    {
        scanf("%d",&n);
        if (n==3 || n==4)
        {
            printf("%d %d
    %d",1,n-1,n-1);
            return 0;
        }
        v.pb(2);n-=2;now=3;
        while (n >= now)
        {
            n-=now;
            v.pb(now);
            now++;
        }
        now = v.size()-1;
        while (n)
        {
            v[now]++;
            now--;
            n--;
            if (now==-1)
                now = v.size()-1;
        }
        a[1] = 1;
        int le = 1,len = v.size();
        for (int i = 0;i <= len-1;i++)
        {
            int x = 0;
            for (int j = 1;j <= le;j++)
            {
                a[j] = a[j]*v[i] + x;
                x = a[j]/10;
                a[j]%=10;
            }
            while (x>0)
            {
                le++;
                a[le] = x;
                x = a[le]/10;
                a[le]%=10;
            }
        }
        for (int i = 0;i <= len-1;i++)
        {
            printf("%I64d",v[i]);
            if (i==len-1)
                puts("");
            else
                putchar(' ');
        }
        for (int i = le;i >= 1;i--)
            printf("%I64d",a[i]);
        return 0;
    }
    
  • 相关阅读:
    JavaScript
    94.Binary Tree Inorder Traversal
    144.Binary Tree Preorder Traversal
    106.Construct Binary Tree from Inorder and Postorder Traversal
    105.Construct Binary Tree from Preorder and Inorder Traversal
    90.Subsets II
    78.Subsets
    83.Merge Sorted Array
    80.Remove Duplicates from Sorted Array II
    79.Word Search
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626684.html
Copyright © 2020-2023  润新知