題目:給你一根長度為 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
提示:這個題和剪繩子i一樣的描述,就是資料範圍變大了。剪繩子可以用動態規劃或者貪心做,這道題對於使用dp難度就增大了一些,因為資料範圍變得比較大時,long已經不足以去儲存中間結果的狀態,那麼這個題範圍變大的本意是想讓我們使用貪心演算法能更好的求解。
首先根據算術幾何均值不等式(n1+n2+n3…+na)/a>=(n1xn2…na)^(1/a),當且僅當n1=n2=…na時後者能取到最大值。因此我們可以得出若想要乘積最大,應該將繩子盡可能等分切割。
那麼問題來了,我們均等切割繩子,每一段要求多長呢?切成每段為1也是均等分,不過這樣顯然是不行的。那麼到底怎麼求每段的長度最優呢?
我們假設分割a段,每段長度為x,則總長n=ax —》x^a= x^(n/x)= (x^(1/x)) ^(n), 即轉化為求x^(1/x)的最大值。
我們再對x求導可知x=e≈2.7時可以取到極大值。又因為當x取2時有2^(1/2)≈1.41; 當x取3時有3^(1/3)≈1.44。所以我們可以得出結論:
要想得到乘積的最大值,我們應盡可能將繩子以3為單位分成多分。
切分規則:
最優:3。把繩子盡可能切為多個長度為3的片段,留下的最後一段繩子的長度可能為 0,1,2 三種情況。
次優:2。若最後一段繩子長度為 2;則保留,不再拆為 1+1。
最差:1 。若最後一段繩子長度為 1;則應把乙份 3 + 1替換為 2 + 2,因為 2×2>3×1。演算法流程:
當n≤3 時,按照規則應不切分,但由於題目要求必須剪成 m>1段,因此必須剪出一段長度為1的繩子,即返回 n - 1。
當 n>3時,求n除以3的整數部分a和餘數部分 b(即 n = 3a + b),並分為以下三種情況:
當 b = 0時,直接返回 3^a%1000000007;
當 b = 1時,要將乙個1+3轉換為2+2,因此返回 3^(a-1)×4%1000000007;
當 b = 2時,返回 3^a ×2%1000000007。
我們可以結合快速冪取餘演算法和貪心演算法來求解本題。
首先,我們得知道乙個公式(a^b) mod c=((a mod c)^b) mod c
當b為偶數的時候,a^b= (a^2 )^(b/2);
當b為奇數的時候,a^b= a*(a^2 )^((b-1)/2)。
//快速取餘演算法
long pow_mod(long a,long b)
return res;
}
結合了快速取餘演算法後我們再結合貪心演算法**如下:
class solution
private:
//快速取餘演算法
long pow_mod(long a,long b)
return res;}};
**如下:
class solution
// 最後n的值只有可能是:2、3、4。而2、3、4能得到的最大乘積恰恰就是自身值
// 因為2、3不需要再剪了(剪了反而變小);4剪成2x2是最大的,2x2恰巧等於4
return res*n%1000000007;}};
為什麼要模1000000007。 參考*
大數相乘,大數的排列組合等為什麼要取模一、1000000007是乙個質數(素數),對質數取余能最大程度避免結果衝突/重複二、int32位的最大值為2147483647,所以對於int32位來說1000000007足夠大。int64位的最大值為2^63-1,用最大值模1000000007的結果求平方,不會在int64中溢位。
所以在大數相乘問題中,因為(a∗b)%c=((a%c)∗(b%c))%c,所以相乘時兩邊都對1000000007取模,再儲存在int64裡面不會溢位。總結一下,這道題要模1000000007的根本原因是標準答案取模了1000000007。不過大數情況下為了防止溢位,模1000000007是通用做法,原因見第一點。
剪繩子 演算法 424,劍指 Offer 剪繩子
給你一根長度為 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。示例 1 ...
劍指Offer 剪繩子 和剪繩子
劍指offer 剪繩子 題目描述 給你一根長度為 n 的繩子,請把繩子剪成整數長度的 m 段 m n都是整數,n 1並且m 1 每段繩子的長度記為 k 0 k 1 k m 請問 k 0 k 1 k m 可能的最大乘積是多少?例如,當繩子的長度是8時,我們把它剪成長度分別為2 3 3的三段,此時得到的...
劍指offer 剪繩子
題目 給你一根長度為n繩子,請把繩子剪成m段 m n都是整數,n 1並且m 1 每段的繩子的長度記為k 0 k 1 k m k 0 k 1 k m 可能的最大乘積是多少?例如當繩子的長度是8時,我們把它剪成長度分別為2 3 3的三段,此 時得到最大的乘積18。思路 動態規劃 任何動態規劃都是由遞迴演...