给你一根长度为 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来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/jian-sheng-zi-ii-lcof
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
乍一看,这道题和剪绳子(一)没啥区别,细一看,这道题要求将结果取模,
好家伙,这道题的每一个测试用例都非常大,非常容易发生溢出的情况
我们需要针对剪绳子(一)的写法进行一些调整
置于具体的算法此处不再做解释,直接参考
循环幂求余法
这里针对于大数,我们在每一次乘法,的时候都需要模上 1000000007,
并且将我们的x,res修改成long int(已经测过int的话会溢出)
class Solution {
public:
int cuttingRope(int n) {
if(n<=3)
{
return n-1;
}
long int x=n/3;
int y=n%3;
long int res=1;
if(y==0)
{
while(x--)
{
res=(3*res)%1000000007;
}
return res;
}
if(y==1)
{
x=x-1;
while(x--)
{
res=(3*res)%1000000007;
}
res=(res*4)%1000000007;
return res;
}
while(x--)
{
res=(3*res)%1000000007;
}
res=(res*2)%1000000007;
return res;
}
};
快速幂算法
假如要求
,由于五是奇数,所以我们可以把一个3提取出来,变成
乘3
然后3的四次方是偶数,可以拆分为
×
也就是说计算
其实只需要先算出3的平方9,然后再算出9的平方81,最后再乘上那个单独的3就可以得出243了。
下面我们就定义了一个remainder来实现我们的上述算法
class Solution {
public:
//x的值一定要是long,否则会存不下
//返回的remainder的值也一定要是long否则会存不下
//x为底数,a为指数,p为要取的模
long remainder(long x,int a,long p)
{
//rem为我们最终快速幂乘法的返回结果
int rem=1;
while (a>0)
{
//如果a是奇数的话,我们就直接将这个多出来的底数乘给我们的返回结果
//并且每一步运算都要对p取模防止溢出
if ((a%2)==1)
{
rem=(rem*x)%p;
}
//如果是偶数的话,就直接平方再取模
x=(x*x)%p;
//然后我们的指数就可以直接整除2了
//这样就实现了快速幂算法
a/=2;
}
return rem;
}
//下面对我们之前的代码进行一些微调即可
int cuttingRope(int n) {
long p=1000000007;
if(n<=3)
{
return n-1;
}
long int x=n/3;
int y=n%3;
long int res=1;
if(y==0)
{
return remainder(3,x,p);
}
if(y==1)
{
x=x-1;
res=(remainder(3,x,p)*4)%p;
return res;
}
res=(remainder(3,x,p)*2)%p;
return res;
}
};
本文含有隐藏内容,请 开通VIP 后查看