1 条题解

  • 0
    @ 2026-4-20 21:47:52

    好的,我们结合题目与给出的核心观察,来写一份详细的中文题解。


    题目回顾

    我们定义:

    • 一个数 xx美丽度 = 二进制表示中 11 的个数。
    • 一个数组的美丽度 = 所有元素美丽度之和。
    • 一次操作:选择一个 aia_i,将其增加 11
    • 最多进行 kk 次操作,求数组美丽度的最大值。

    核心观察(Key Observation)

    对于一个数 xx,要增加它的美丽度,最优方式是:找到二进制中 最低位的 0,把它变成 1,并把所有更低位都变成 0。

    为什么这样是最优的?

    xx 的最低 0 位在第 pp 位(2p2^p 的值),记为特殊位。

    • 将特殊位从 0 变 1,同时更低位全变 0,得到的数是:

      $$y = x \ \text{with bit p set to 1, lower bits cleared} $$
    • xx 增加到 yy 的过程:

      • 每次增加 1,最低的 0 位要么是 pp,要么是比 pp 更低的位。
      • 但一旦最低 0 位低于 pp,比 pp 高的位不变,而低于 pp 的位中存在 0,此时的美丽度 ≤ yy 的美丽度。
      • 直到到达 yy 之前,美丽度不会超过 yy

    因此:[x,y)[x, y) 之间的任何数,美丽度都 ≤ 原数 xx 的美丽度,只有到达 yy 时,美丽度才真正增加。

    结论:要让 xx 的美丽度增加,最少操作数就是 yxy - x,且这是当前最优的“增一美”方式


    转化为贪心策略

    因为美丽度只关心二进制 11 的个数,且增加一个数的美丽度的最优方式是“清除低位的 1 并设置一个更高位的 0 为 1”,我们可以全局贪心:

    1. 初始美丽度 = 所有数的二进制 1 的个数和。
    2. 维护一个“位池”:对于每个二进制位 jj(从低位到高位),统计当前所有数中,这个位上是 0 的数量。
    3. 从低位 j=0j = 0 到高位:
      • 如果第 jj 位上有 cntcnt 个 0,且 k2jk \ge 2^j
        • 我们最多可以一次将 cntcnt 个数的第 jj 位从 0 变成 1,每操作一个数需要 2j2^j 次操作,同时该数的美丽度 +1。
        • 因此,这一步能增加的总美丽度 = min(cnt,k/2j)\min\left(cnt, \lfloor k / 2^j \rfloor\right)
        • 操作后,kk 减少 min(cnt,k/2j)×2j\min(cnt, \lfloor k / 2^j \rfloor) \times 2^j
    4. 继续向高位迭代,直到 kk 不够或没有 0 位。

    为什么贪心正确?
    因为低位的 2j2^j 更小,用更少的操作获得 +1 美丽度,性价比更高,所以应该先处理低位。


    算法步骤

    nn 个数,a[1..n]a[1..n]kk 次操作。

    1. 初始化 ans=i=1npopcount(a[i])ans = \sum_{i=1}^n \text{popcount}(a[i])
    2. 初始化一个数组 zero_cnt[bit]zero\_cnt[bit],表示所有数在第 bitbit 位上为 0 的个数。
    3. 对于 bit=0,1,2,,60bit = 0, 1, 2, \dots, 60(因为 ai109<230a_i \le 10^9 < 2^{30},但操作可能进位到 2602^{60} 内):
      • 如果 k<2bitk < 2^{bit},则无法继续。
      • 可以操作的次数 $ops = \min(zero\_cnt[bit], \lfloor k / 2^{bit} \rfloor)$。
      • ansans 增加 opsops
      • kk 减少 ops×2bitops \times 2^{bit}
    4. 输出 ansans

    复杂度

    • 每个数最多处理 log(109+k)60\log(10^9 + k) \approx 60 个位。
    • 总复杂度 O(nlogmax(ai+k))O(n \log \max(a_i + k)),完全可过。

    示例验证

    用题目第一个例子:
    a=[0,1,7,2,4]a = [0, 1, 7, 2, 4], k=2k = 2

    初始:

    • 二进制: 0: 0
      1: 1
      7: 111
      2: 10
      4: 100

    popcount 和 = 0 + 1 + 3 + 1 + 1 = 6(不对,等一下,我们验证)
    仔细算: 0 → 0 个 1
    1 → 1 个 1
    7 → 3 个 1
    2 → 1 个 1
    4 → 1 个 1
    总和 = 0+1+3+1+1 = 6

    但题目输出是 8,说明操作后 +2 个 1。

    贪心: bit 0(20=12^0=1):所有数最低位:
    0(0),1(1),7(1),2(0),4(0) → 0 的个数 = 3
    k=2k=2ops=min(3,floor(2/1))=2ops = min(3, floor(2/1)) = 2
    ans = 6 + 2 = 8
    k = 2 - 2*1 = 0
    结束,输出 8 ✅

    • 1

    信息

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