• poj 1032(整数拆分)


    给你一个n问求使得 a1+a2+..ak==n时 a1*a2*..ak最大。。a1 a2.....不相等。(没看懂题目意思。。)

    以下转自http://blog.himdd.com/?p=1918

    思路:将一个数分成2份,如何分,使得这两个数乘积最大。答案是将这个数平分,证明是求x*(n-x)的最大值。基于这种思路,将N分成乘积最大的不相等的多份,应使得其中每份的数相差尽量少,即差值为1的等差数列为最理想状态。构造了一个等差数列以后,再根据剩余值对整个数列的值进行调整。使得相邻元素差值达到最小。这里注意,等差数列的构造应以2为首项,1为首项的话,对乘积没影响。。。
    (以下证明是从网上得来的)
    由题意知,这种分解的数目是有限的,因此,最大积存在;
    假设最大积的分解为:
    N=a1+a2+a3+…+a[t-2]+a[t-1]+a[t] (t是分解的数目,a1<a2<a3<...<a[t-2]<a[t-1]<a[t])
     下面是该数列的性质及其证明:
    1)a1>1;
    如果a1=1,则a1和a[t]可以由a[t]+a1=a[t]+1来替代,从而得到更大的积;

    2)对于所有的i,有a[i+1]-a[i]<= 2;
    如果存在i使得a[i+1]-a[i]>=3,则a[i]和a[i+1]可以替换为a[i]+1,a[i+1]-1,从而使乘积更大;

    3)最多只存在一个i使得a[i+1]-a[i]=2;
    如果i< j且a[i+1]-a[i]=2、a[j+1]-a[j]=2,则a[i],a[j+1]可以替换为a[i]+1,a[j+1]-1,从而使得乘积更大;

    4)a1<=3;
    如果a1>=4,则a1和a2可以替换为2,a1-1,a2-1,从而使得乘积更大;

    5)如果a1=3且存在i满足a[i+1]-a[i]=2,则i一定等于t-1;
    如果i<t-1,则a[i+2]可以替换为2,a[i+2]-2,从而使得乘积更大;< p="">

    将上面5条性质综合一下,得到该数列满足:
    1)1< a1< 4
    2)a[i+1]-a[i] <=2(该序列按升序排序)
    3)a[i+1]-a[i]=2的情况最多只有一个

    因此,我们得到最大的乘积的做法就是求出从2开始的最大连续(由上面总结的性质2和3可知)自然数列之和A,使得A的值不超过N,具体分析如下:
    对输入的N,找到k满足:
    A=2+3+4+...+(k-1)+k <= N < A+(k+1) = B
    假设N=A+p(0<=p< k+1),即A+p是最大积的数列
    1)p=0,则最大积是A;
    2)1<=p<=k-1,则最大积是B-{k+1-p},即从数列的最大项i开始,从大到小依次每项加1,知道p=0为止;
    3)p=k,则最大积是A+p=A+k=A-{2}+{k+2};( =3+4+...+k+( k+2) );

     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <algorithm>
     6 
     7 using namespace std;
     8 
     9 #define MAXN 150
    10 int ans[MAXN];
    11 int n,k,sum;
    12 
    13 int main()
    14 {
    15     while(~scanf("%d",&n))
    16     {
    17         memset(ans,0,sizeof(ans));
    18         k=0;
    19         ans[k++]=2;
    20         ans[k++]=3;
    21         sum=5;
    22         while(sum+ans[k-1]+1<=n)
    23         {
    24             ans[k]=ans[k-1]+1;
    25             sum+=ans[k++];
    26         }
    27         int tmp=n-sum;
    28         while(tmp>0)
    29         {
    30             for(int i=k-1;tmp>0 && i>=0;i--)
    31                 ans[i]++,tmp--;
    32         }
    33         printf("%d",ans[0]);
    34         for(int i=1;i<k;i++)
    35             printf(" %d",ans[i]);
    36         printf("\n");
    37     }
    38     return 0;
    39 }
  • 相关阅读:
    LiteFlow 按照规则配置进行复杂流转
    ImageCombiner 服务端合图
    forest HTTP调用API框架
    smart-doc API文档生成工具
    YAML语法和用法
    拓展mybatisPlus 支持批量插入
    ModbusRTU控制SV660P说明
    .NET RulesEngine(规则引擎)
    Win10自动更新有效强制永久关闭
    Redis 到底是怎么实现“附近的人”这个功能的?
  • 原文地址:https://www.cnblogs.com/Missa/p/2719943.html
Copyright © 2020-2023  润新知