Loading web-font TeX/Math/Italic
Gravatar
yrtiop
积分:2109
提交:311 / 811

Pro618  [金陵中学2007] 最优分解方案

看到这道题,最朴素的想法是用 DFS 求解。

显然这样搜出来的状态数量非常庞大,时间复杂度无法承受,考虑换用 DP 遍历所有状态。

这里有两个方法。

法一:(60pts)

f_i 表示正整数 i(i \in N^+) 分解后的最大乘积。

这种情况下乍一看似乎无法转移,因为有后效性,前面的数分解出 k 那么后面就不能分解出 k 了。

既然如此,可以尝试改变状态,多加几维限制。

思考后得出:设 f(i,j) 表示正整数 i(i \in N^+) 分解出的最大整数为 j 时的最大乘积。

初始状态:\forall i \in [0,n],f(0,i) = 1

状态转移方程:f(i,j) = \max\limits_{k=1}^{j - 1} f(i - j,k) \times j

最终状态 \max\limits_{i=0}^n f(n,i)

然而这样是 O(N^3) 的,考虑优化。

s(i,j) = \max\limits_{k=1}^j f(i,k)

则状态转移方程会变成:f(i,j) = s(i - j,j - 1) \times j

初始 \forall i \in [0,n],s(0,i) = 1

答案为 s(n,n)

这样用 unsigned long long 可以过 60% 的测试数据,但换成高精度则会出现一堆绿色的字母。

(upd:测试时发现,其实根据数学知识,每次转移的 j 并不会太大,有兴趣的可以打个表把 j 的范围缩小些,这样应该能直接 AC)


CODE


法二:

(此方法我暂时给不出严谨的证明,只能感性理解给个大概意思)

再仔细想一想,难道这个 DP 就一定要二维吗?

再想一想,假设我们把 i 分解为 \{a_1,a_2\ldots a_k \},要枚举一个 a_j(1\le j \le k) 进行状态转移。

不难发现,每个数字分别顺序的先后并不影响它对答案的贡献。

换言之,不论枚举的顺序如何,最优状态也一定会被遍历到。

基于此,我们令 f_ii 分解的最优答案,用 bitset 或者 bool 数组记录一下哪些数字被选上了,转移一下就好了。

这个转移方程相当简单,就不写了,详情见 AC 代码。




2022-05-20 21:16:44    
我有话要说
Gravatar
op_组撒头屯
积分:3060
提交:341 / 681
回复@Skylake :orz

2022-05-22 10:24:18    
Gravatar
lihaoze
积分:1325
提交:363 / 757
回复@Skylake : 我的做法一开始和大佬的思路一样,不过后来用滚动数组优化了一下,代码就变得很简洁了

2022-05-23 13:51:32