题⽬描述

给你⼀根⻓度为 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 取模。

思路解答

动态规划

自底向上计算最优解

  • 时间复杂度:O(n²),外层循环n-3次,内层循环i/2次

  • 空间复杂度:O(n),需要dp数组存储中间结果

优化动态规划

在上面版本上优化状态转移方程,提高代码效率,直接比较j*(i-j)j*dp[i-j]的最大值

dp[i] = max(max(j × (i-j), j × dp[i-j])) 其中 1 ≤ j < i

  • j × (i-j):剪一刀的情况

  • j × dp[i-j]:剪多刀的情况

  • 时间复杂度:O(n²),双重循环

  • 空间复杂度:O(n),dp数组空间

贪心算法(最优解)

我们仔细观察就会发现:要想乘积⽐较⼤,在没有1的前提下,优先使⽤3,如果出现1,那么优先使⽤2

⽐如:

结果很不幸:运⾏超时:您的程序未能在规定时间内运⾏结束,请检查是否循环有错或算法复杂度过⼤。

于是我们需要想到其他的⽅式,如何快速计算 3 的 n 次⽅,这是我们需要解决的问题,因为在尽量凑 3的前提下,有以下三种情况:

  • 被 3 整除 等于 n :直接计算 3 的 n 次幂

  • 被 3 取余数为1,结果等于 n :直接计算 3 的 (n-1) 次幂,再乘以4,为什么呢?因为余数是1,我们避免有1,需要借出 3,和 1凑成为 4,4 分段之后的最⼤乘积也是 4(2 * 2)

  • 被 3 取余数为 2,结果等于 n:直接计算 3 的 n 次幂,再乘以2

也就是说,当n≥5时,优先剪出长度为3的段;剩余4时剪成2×2

为什么选择3?

  1. 数学证明:当n ≥ 5时,3(n-3) ≥ 2(n-2) > n

  2. 接近自然底数e:最优分段长度应接近e ≈ 2.718,3是最接近的整数

  3. 4的特殊处理:2×2 > 3×1,所以剩余4时剪成2×2而不是3×1

执行过程示例(n=10):

在计算幂次⽅的时候,为了避免溢出,在每次相乘的时候,都需要除以998244353 ,为了计算快,每次以⾃身相乘的⽅式计算,代码如下:

  • 时间复杂度:O(1),只有常数次操作

  • 空间复杂度:O(1),只使用固定变量

数学公式法(理论最优)

根据n除以3的余数直接套用公式