剑指 Offer 14- II. 剪绳子 II
给你一根长度为 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
经过上述推导与证明,需要尽可能的将绳子三等分,才可以使乘积最大,因此考虑n%3
余数的情况
- 余数为
0
, f ( n ) = 3 a f(n) = 3^a f(n)=3a; - 余数为
1
,由于4 > 1 * 3
,因此可以拿出一个3
和1
组成4
,此时 f ( n ) = 3 a − 1 × 4 f(n) = 3 ^ {a - 1} \times 4 f(n)=3a−1×4 - 余数为
2
, f ( n ) = 3 a × 2 f(n) = 3^a\times2 f(n)=3a×2
C++版本 |
class Solution {
public:
using LL = long long;
constexpr static int MOD = 1e9 + 7;
int cuttingRope(int n) {
if(n <= 3) return n - 1;
int a = n / 3, b = n % 3;
LL ans = 0;
if(b == 0) ans = quick_pow(3,a);
else if(b == 1) ans = quick_pow(3,a - 1) * 4 ;
else ans = quick_pow(3,a) * 2;
return ans % MOD;
}
private:
//快速幂取模
LL quick_pow(LL a,LL b){
LL ans = 1;
while(b){
if(b & 0x1) ans = (ans * a) % MOD;
a = (a * a) % MOD;
b >>= 1;
}
return ans % MOD;
}
};
Python版本 |
class Solution:
def cuttingRope(self, n: int) -> int:
if n <= 3:
return n - 1
ans = 0;
a,b = n // 3,n % 3
if b == 0:
ans = (3 ** a)
elif b == 1:
ans = (3 ** (a - 1)) * 4
else:
ans = (3 ** a) * 2
return ans % (10 ** 9 + 7)