【剑指offer-C++】JZ83:剪绳子(进阶版)

【剑指offer-C++】JZ83:剪绳子[进阶版]

    • 题目描述
    • 解题思路

题目描述

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

由于答案过大,请对 998244353 取模。

数据范围:2≤n≤1014

进阶:空间复杂度 O(1) , 时间复杂度 O(logn)。

输入:4
返回值:4
说明:拆分成 2 个长度为 2 的绳子,2 * 2 = 4 
输入:5
返回值:6
说明:剪成一个长度为 2 的绳子和一个长度为 3 的绳子,答案为2*3=6 
输入:874520
返回值:908070737

解题思路

剪绳子(进阶版):最直观的想法是,快速幂加上快速乘法。剪绳子当每一段长度为3时乘积最大,故使用number对3取余得到res,取商得到num,当res等于0直接返回3的num次方,当res等于1则取一个3凑成4即返回3的num-1次方再乘以4,当res等于2直接返回3的num次方再乘以2。但是由于数据较大,故乘方运算要使用快速幂实现,而乘法运算要使用快速乘法即乘法转换为加法计算。具体注释如下面代码所示。

//乘法
long long mod=998244353;
// 将乘法转换为加法 计算a乘以b
long long fast(long long a,long long b)
{
    long long res=0;
    a%=mod;
    b%=mod;
    while(b)
    {
       // b的当前位为1
       if(b&1)
       {
           res+=a;
           res%=mod;
       }
       b>>=1;
       a<<=1;  // 相当于乘以2 因为b是二进制 b右移对应的a左移
       a%=mod;
    }
    return res;
}
// 快速幂运算计算a的b次方
long long quick(long long a,long long b)
{
    // 记录结果
    long long res=1;
    while(b)
    {
       //b的当前位为1 将其当前乘入结果
       if(b&1)
         res=fast(res,a);
       // 底数a向前一位代表进位 即为下一次的底数
       a=fast(a,a);
       // 指数b右移一位
       b>>=1;
    }
    return res;
}
long long cutRope(long long number) 
{
    // 长度为n分为m段 且m>1 n=2则1*1=1 n=3则1*2=2
    if(number<=3)
       return number-1;
    long long num=number/3;
    long long res=number%3;
    if(res==0)
       return quick(3,num);
    else if(res==2)
       return fast(2,quick(3,num));
    return fast(4,quick(3,num-1));
}

你可能感兴趣的:(剑指offer,c++,算法,开发语言)