• 剪绳子 牛客网-剑指Offer_编程题


    题目描述

    给你一根长度为n的绳子,请把绳子剪成m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],...,k[m]。请问k[0]xk[1]x...xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。

    题目分析

    首先,将该题目可以建模成:

    (一)当不考虑未知数是否为整数的情况

     可知,首先要找到最佳的m,再找到最佳的m个段长。若m固定的话,怎样将n分配到m段才能让这m段的乘积最大呢?很容易想到,当n均匀分配到m段时,m段长的乘积最大,这也是可以证明得到的。

     假设m=2,则x+y=n,f(x,y)=x*y=x*(n-x)=nx-x2,对于这样一个二次函数,它具有最小值n2/4,对应x=y=n/2,这个大家都知道。那么推广到m未知的情况,是怎么样的?
     
     根据

     可以消元得到

     对函数求偏导并令所有偏导等于0,即可得到极值:

    ...

     

     化简得到:

    ...

     

    即:

    那么可知

    此时f函数在m固定的情况下具有最大值,那么其实m也是个未知数,如何确定m使得f函数最大呢?

    我们又可以使用求导令其等于0的方法,不过我们可以稍稍变换一下函数使其更好求导,即函数前加个ln:

    求出了lnf的极值点,那么也就求出了f的极值点:

    可得:

    故可知:上式情况下函数f具有最大值

    (二)考虑到未知数应为整数的情况

    根据我们的建模公式,咱们的未知数都为整数,而在上一步,我们求得的解很可能产生小数,所以我们需要调整。

    m的范围最好是在n/e左右,那么就考虑m要么为n/e左边的整数,要么为其右边的整数。

    同理,分出来的段长要么为2,要么为3。

    python编程实现 

    1 for i in range(2, 61):
    2     m = i/math.e
    3     m1 = int(m) if int(m) > 1 else 2
    4     m2 = m1 + 1 if int(m) > 1 else 2
    5     c1 = int(i/m1)
    6     c2 = int(i/m2)
    7     r3 = ((c1+1) ** (i - c1 * m1)) * (c1 ** (m1 - i + c1 * m1))
    8     r4 = ((c2+1) ** (i - c2 * m2)) * (c2 ** (m2 - i + c2 * m2))
    9     print(r3 if r3 >= r4 else r4)
  • 相关阅读:
    [原] KVM 虚拟化原理探究(6)— 块设备IO虚拟化
    [原] KVM 虚拟化原理探究(5)— 网络IO虚拟化
    [原] KVM 虚拟化原理探究(4)— 内存虚拟化
    [原] KVM 虚拟化原理探究(3)— CPU 虚拟化
    [原] KVM 虚拟化原理探究(2)— QEMU启动过程
    [原] KVM虚拟机网络闪断分析
    [原] KVM 环境下MySQL性能对比
    [源]云计算技术堆栈系列——鸟瞰
    [原] 利用 OVS 建立 VxLAN 虚拟网络实验
    [原] Cgroup CPU, Blkio 测试
  • 原文地址:https://www.cnblogs.com/zhuangzi101/p/11774309.html
Copyright © 2020-2023  润新知