原题链接:剪绳子(进阶版)_牛客题霸_牛客网
描述:
给你一根长度为 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≤10的14次方
进阶:空间复杂度 O(1), 时间复杂度 O(logn)
解题思路:
分为两步,第一步求最终的值,第二步求最终的值取模结果:
第一步:
我们这个这样拆分一下,2的最大值是
(n=2)=>2
(n=3)=>3
(n=4)=>2*2=4
(n=5)=>3*2=6
(n=6)=>3*3=9
(n=7)=>3*2*2=12
(n=8)=>3*3*2=18
(n=9)=>3*3*3=27
所以其实我们可以得到一个这样的结论,就是把绳子尽量多的拆分出更多的3。
如果除以3余数为0时,那就拆分为x*3的形式;
如果除以3余数为1时,那就拆分为x*3+2+2的形式;
如果除以3余数为2时,那就拆分为x*3+2的形式;
第二部:取模
这个要借鉴快速幂运算,
(a*b)%p = (a%p * b%p)%p
我们要求的3的n次方,则个n会很大,那我们就不断的取模求值。
则3^n = (3^(n/2)%p*3^(n/2)%p)%p
这样的话,
代码:
public long cutRope(long number) {
if (number == 2) {
return 1;
}
if (number == 3) {
return 2;
}
long sum = 1;
long yushu = number % 3;
long times;
int base = 1;
if (yushu == 0) {
times = number / 3;
} else if (yushu == 1) {
times = number / 3 - 1;
base = 4;
} else {
times = number / 3;
base = 2;
}
sum = pow(times, 998244353);
sum = sum * base;
return sum % 998244353;
}
public long pow(long times, int moshu) {
if (times == 0) {
return 1;
}
if (times == 1) {
return 3;
}
long pow = pow(times / 2, moshu);
long l = pow * pow % moshu;
if (times % 2 == 0) {
return l;
}
return 3 * l;
}