题目描述
给你一根长度为 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 取模。
思路 & 解答
这道题其实如果不是数值很大,我们可以使用动态规划来完成:
每个长度的绳子,要么最长的情况是不剪开(长度是本身),要么长度是剪开两段的乘积。因此每个长度length
都需要遍历两个相加之后等于length
的乘积,取最大值。
初始化值长度为1
的值为1
,从长度为2
开始,每一种长度都需要遍历两个子长度的乘积。
C++
代码如下:
但是由于数值比较大,直接乘积的时候就溢出了,我们仔细观察就会发现:
要想乘积比较大,在没有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
在计算幂次方的时候,为了避免溢出,在每次相乘的时候,都需要除以998244353
,为了计算快,每次以自身相乘的方式计算,代码如下:
C++
代码如下: