给你一根长度为 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;
-
- }
- };
