1 条题解

  • 0
    @ 2026-9-3 10:56:53

    题解

    思路

    把已经获得的块数超过 kk 的状态统一截断为 kk。若当前还需要把块数再扩大到原来的 rr 倍,沿新维度切成 cc 份后,新的需求为 ⌈r/c⌉\lceil r/c\rceil,体积倍率为 ⌊ai/c⌋/ai\lfloor a_i/c\rfloor/a_i。

    子任务 1

    枚举每一维的 bi=1,2,…,aib_i=1,2,\ldots,a_i,在叶子检查乘积是否至少为 kk,直接计算目标值。复杂度为 O(∏ai)O(\prod a_i)。

    子任务 2

    令 dp[j] 表示处理若干维后恰好得到 min(实际块数,k)=j 时的最大目标值前缀。对每个有效 jj 枚举切分数 cc,当 jc<kjc<k 时正常转移;达到 kk 后只需考虑最小的 c=⌈k/j⌉c=\lceil k/j\rceil。利用调和级数,单维转移为 O(klog⁡k)O(k\log k)。

    子任务 3

    改用“剩余倍率”状态。所有 ⌈k/i⌉\lceil k/i\rceil 只有 O(k)O(\sqrt k) 个不同值。对于一个剩余倍率 rr,其转移目标 ⌈r/c⌉\lceil r/c\rceil 同样只有 O(r)O(\sqrt r) 个不同值;对每段只保留最小 cc,因为它让 ⌊ai/c⌋\lfloor a_i/c\rfloor 最大。

    依次生成商相同区间的左端点:当前值为 q=⌈r/c⌉q=\lceil r/c\rceil 时,下一个左端点为 ⌈r/(q−1)⌉\lceil r/(q-1)\rceil。预处理所有压缩状态及转移后进行滚动 DP。

    做法

    1. 枚举并编号全部不同的 ⌈k/i⌉\lceil k/i\rceil。
    2. 对每个压缩状态生成所有不同目标状态及对应的最小切分数 cc。
    3. 初始剩余倍率为 kk,初始数值为 kk。
    4. 逐维乘上 ⌊ai/c⌋/ai\lfloor a_i/c\rfloor/a_i 并取最大值,最终读取剩余倍率为 11 的状态。

    正确性证明

    状态 rr 精确表示当前仍需把块数扩大至少 rr 倍;选择 cc 后新需求为 ⌈r/c⌉\lceil r/c\rceil,因此转移无误。对产生同一新需求的多个 cc,较小的 cc 具有不小的 ⌊ai/c⌋\lfloor a_i/c\rfloor,所以只保留区间左端点不丢失最优解。DP 枚举每一维的全部不同有效决策,最终 r=1r=1 恰表示总块数至少为 kk,故答案正确。

    复杂度

    满分算法时间复杂度为 O(nk3/4)O(nk^{3/4}),空间复杂度为 O(k+nk3/4)O(\sqrt k+nk^{3/4}) 的预处理转移与滚动状态;实现中 DP 本身为 O(k)O(\sqrt k) 空间。中档为 O(nklog⁡k)O(nk\log k),小档为指数复杂度。

    • 1

    信息

    ID
    1367
    时间
    2000ms
    内存
    512MiB
    难度
    10
    标签
    递交数
    1
    已通过
    0
    上传者