1 条题解

  • 0
    @ 2025-12-9 20:02:48

    L2174. 「FJOI2016」神秘数 - 完整题解

    题目描述

    给定一个长度为 nn 的序列 a1,a2,,ana_1, a_2, \dots, a_n,有 mm 个询问。对于每个询问 [l,r][l, r],考虑由 al,al+1,,ara_l, a_{l+1}, \dots, a_r 构成的可重复数字集合,求这个集合的神秘数——即最小的不能被该集合的某个子集的和表示的正整数。

    数据范围:

    n,m105n, m \leq 10^5

    ai109\sum a_i \leq 10^9

    核心思路分析

    1. 问题转化 我们需要快速求出区间 [l,r][l, r] 中数字组成集合的神秘数。直接枚举所有子集显然不可行。

    2. 关键观察 设当前已经能够表示出 [1,R][1, R] 中的所有整数,考虑下一步:

    情况1:如果集合中存在某个数 xR+1x \leq R+1

    那么我们可以用 xx 加上 [1,R][1, R] 中的某些数,表示出 [x,x+R][x, x+R]

    由于 xR+1x \leq R+1,区间 [1,R][1, R][x,x+R][x, x+R] 会合并成 [1,x+R][1, x+R]

    新的表示范围变为 [1,R][1, R'],其中 R=R+xR' = R + x

    情况2:如果集合中所有数都 >R+1> R+1

    那么 R+1R+1 无法被表示

    答案就是 R+1R+1

    1. 贪心算法 扩展上面的思路:不是只加一个 R+1\leq R+1 的数,而是一次性加入所有 R+1\leq R+1 的数。

    算法流程:

    text 初始化 R = 0 循环: 设 S = 区间内所有 ≤ (R+1) 的数的和 如果 S > R: R = S # 能表示的范围扩展到 [1, S] 否则: 输出 R+1 作为答案 结束循环 正确性证明:

    设当前能表示 [1,R][1, R],令 X=R+1X = R+1

    查询所有 X\leq X 的数的和 SS

    如果 S=RS = R:说明没有新的数可以加入,XX 无法表示

    如果 S>RS > R:设新增的数为 v1,v2,,vkv_1, v_2, \dots, v_k(都 X\leq X

    对于每个 viv_i,由于 viX=R+1v_i \leq X = R+1,且已能表示 [1,R][1, R]

    可以表示 [vi,vi+R][v_i, v_i + R],这些区间会合并成 [1,S][1, S]

    因此更新后能表示 [1,S][1, S]

    1. 复杂度分析 设最终答案为 ansans

    每次循环中,新的 RR 至少是原来的 RR 加上某个 R+1\leq R+1 的数

    实际上 RR 的增长速度很快(类似倍增)

    循环次数为 O(log(ai))O(\log(\sum a_i)),通常不超过 40 次

    • 1

    信息

    ID
    5957
    时间
    1000ms
    内存
    256MiB
    难度
    8
    标签
    递交数
    1
    已通过
    1
    上传者