题目链接:剪绳子 II LCOF
题目大意:给你一个绳子,长度为n,要求你拆分其为m(m>2)段,并且要求所有段长度的乘积最大
题目思路:比较经典的一个题目了,首先可以想到的一个经典解法是dp的做法,对于一个绳子,我们先任意减去一小段,这样得到的就是更小的绳子,而更小的绳子的最大乘积我们可以得到,因此就有了答案,枚举取最大值即可。
而另一个解法涉及到到数学问题,这个做法的证明可以见官方题解,证明的很好,本质上是证明一个下界,比较容易想到的解法是长度为n的绳子拆分成m段,一定是均分后得到的乘积最大,而通过公式可以求导算出来,分为3的长度是最优的,所以直接用长度为3的来划分即可,其余部分采用快速幂解决,具体见代码
时间复杂度&&空间复杂度:O(log2n)&O(1)
DP做法:
class Solution {
public:
long long dp[1005];
const long long mod = 1e9+7;
void pre(){
dp[0] = 1;
dp[1] = 1;
for(long long i = 2;i <= 60;i++){
long long maxx = -1;
for(long long j = 1;j < i;j++){
maxx = max(maxx,j*max(i-j,dp[i-j]));
}
dp[i] = maxx;
}
}
int cuttingRope(int n) {
pre();
//for(int i = 1;i <= 10;i++) cout<<dp[i]<<endl;
return dp[n];
}
};
数学公式:
class Solution {
public:
const int mod = 1e9+7;
long long quick_mod(long long a,long long b){
long long ans = 1;
while(b){
if(b&1) ans = ans*a%mod;
a = a*a%mod;
b>>=1;
}
return ans;
}
int cuttingRope(int n) {
if(n == 2) return 1;
else if(n == 3) return 2;
if(n%3 == 0) return quick_mod(3,n/3);
else if(n%3 == 1) return quick_mod(3,n/3-1)*4%mod;
else return quick_mod(3,n/3)*2%mod;
}
};