剪绳子 求最大乘积问题

解题思路

本题相比 "剪绳子 I" , n能取得值更大了
如果用Python 得数值类型默认是支持大数的 , 类似3^200 这个数可以表示出来
但是C++中即便是long long (__int64) 都无法表示如此大的数
考虑使用贪心算法,依据就是尽最大努力保证长度3的子段最多 ,进而推出全局最优
要用到一个数学推导
An = X %1007
An+1 = (X *3)%1007 = [ 3 * (X%1007) ] %1007 =[ 3 *An ] % 1007

代码

class Solution {
public:
    int cuttingRope(int n) {
    //    局部最优推出全局最优  尽最大努力保证3 子段最多
    // n%3 ==0 , n^x %1007   x= n/3
    // n%3=1  n^(x) *4 * %1007   x= (n-4)/3 
    // n%3=2 n^(x) *2 % 1007     x = (n-2)/3

    // An = X %1007
    // An+1 = (X *3)%1007 = [ 3 * (X%1007) ] %1007 =[ 3 *An ] % 1007
       if(n<4) return n-1;

       long  res=1; 
       int x=0;
       if(n%3 == 0 ) x=n/3;
       if(n%3 ==1 ) x= (n-4)/3;
       if(n%3==2 ) x= (n-2)/3;
        
       for(int i=0;i<x  ;i++)
       {
           res = ( res* 3) % 1000000007;
       }
        if(n%3 ==1 ) res =( res*4)%1000000007;
        if(n%3 ==2 ) res =( res*2)%1000000007;



        return res;
       
    }
};

附上Python 动态规划的代码 能AC

class Solution:
    def cuttingRope(self, n: int) -> int:
        fn=[0,1,2,3,4,6]  #fn 即 f(x,x1)最大时候
        fnYidao= [0,0,1,2,4,6]
        if n<6 : return fnYidao[n]
        
        for TN in range(6,n+1):
            tmax= TN
            for x in range(0,TN+1):
                val=0
                if x ==TN or x==0 : val= TN
                else :val = fn[x] * fn[TN-x]
                if(val > tmax) : tmax = val
                #print(val)
            fn.append(tmax)
        #print(fn)
        return fn[-1] % 1000000007

C 动态规划的代码 不能AC 最大支持n=120


Python 大数
class Solution {
public:
    int cuttingRope(int n) {
 



    //注意 行不通,因为 3**n 肯定会超过 int所能
    // 子问题 假设dp[i] 表示 【..i】线段能得到的最大乘积 
    // 那么 dp[n]= max(  [n-i] * dp[i] )  i= 1..n-1  i=0 
    //相当于在每个切割点都尝试下 看能否得到 最大  
     //题目要求至少割一刀   dp[n-i] 
    //举例验证  n=8      从i=4 开始 一定要割一刀 才能保证乘积最大
        // dp[1] = 1
        // dp[2] = max(1 * dp[1] , 2) =2 
        // dp[3] = max{2*dp[1] ,dp[1]* dp[2], 3} =3   
        // dp[4] = max{dp[3]*dp[1] , dp[2]*dp[2] , 4}  =     2*2
        // dp[5] = max{dp[4]*dp[1] , dp[3]*dp[2], 5 } =         6
        // dp[6] = max{dp[5]*dp[1] ,dp[4]*dp[2] , dp[3]*dp[3], 6}  = 3*3
        // dp[7] = max{dp[6]*dp[1],dp[5]*dp[2] ,dp[4]*dp[3] , 7}  =12  =   2*3*2
        // dp[8] = max{dp[7]*dp[1],dp[6]*dp[2] ,dp[5]*dp[3],dp[4]*dp[4] , 8}  =3*3 *2 
        // 。。。
       if(n<4) return n-1;
       std::vector<long long > dp(n+1,0);
       dp[1]=1,dp[2] =2 ; dp[3] =3 ;
       
     
       
       for(int i=4;i<=n;i++)
       {
            int endPos= i/2;
            dp[i] = i;
            for(int m=1; m<= endPos; m++)
            {
                
                long long temp= dp[i-m]* dp[m] ;
              //  std::cout << temp <<" "<<  dp[i] << " ";
                if( temp > dp[i]) dp[i] =temp;
            }
            //std::cout << std::endl;
       }

        for(auto x: dp) std::cout << x <<" ";
        return dp[n];
    }
};

题目描述

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

答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。

示例 1:

输入: 2
输出: 1
解释: 2 = 1 + 1, 1 × 1 = 1
示例 2:

输入: 10
输出: 36
解释: 10 = 3 + 3 + 4, 3 × 3 × 4 = 36

提示:

2 <= n <= 1000

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/jian-sheng-zi-ii-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

posted @ 2021-05-17 13:06  boyang987  阅读(138)  评论(0编辑  收藏  举报