剪绳子 求最大乘积问题
解题思路
本题相比 "剪绳子 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
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。