1 条题解

  • 0
    @ 2025-12-9 23:34:34

    题目大意 给定一个长度为 nn 的初始序列 xx,我们可以在其后添加 mm 个属于 [l,r][l, r] 的正整数。得到的新序列长度为 n+mn+m,对其进行 Gobo sort 排序。该算法的期望执行轮数(即步骤 2 的期望执行次数)等于 N!/v(cv!)N! / \prod_{v} (c_v!),其中 N=n+mN = n+mcvc_v 是每个数字 vv 在新序列中的出现次数。目标是选择添加的 mm 个数,使得期望轮数最大,并输出对 998244353998244353 取模的结果。

    问题转化 对于固定的新序列,设不同数字的出现次数分别为 c1,c2,,ckc_1, c_2, \dots, c_k,则成功概率为 vcv!/N!\prod_{v} c_v! / N!,期望轮数为 E=N!/vcv!E = N! / \prod_{v} c_v!。因此,最大化 EE 等价于最小化 vcv!\prod_{v} c_v!

    初始序列给出了部分数字的出现次数。我们只能向 [l,r][l, r] 内的数字添加次数(可以增加已有数字的出现次数,也可以引入新数字)。需要分配 mm 次添加,使得最终的 cv!\prod c_v! 最小。

    贪心策略 考虑每次添加一个数,即让某个数字的出现次数增加 11。设当前数字 vv 的出现次数为 cvc_v,增加一次后,cv!\prod c_v! 会乘以 (cv+1)(c_v+1)。为了使乘积增长最慢,每次应选择当前 cvc_v 最小的数字进行增加。这样,乘数 (cv+1)(c_v+1) 最小,从而整体乘积最小。

    如果 [l,r][l, r] 内有数字未在初始序列中出现,则它们的出现次数视为 00,同样参与贪心。

    具体实现 统计初始出现次数 对初始序列排序,统计每个数字的出现次数。对于在 [l,r][l, r] 内的数字,记录它们的出现次数;对于不在 [l,r][l, r] 内的数字,它们的出现次数固定,直接将其阶乘乘到分母 den\text{den} 中(初始 den=1\text{den}=1,最终 den=cv!\text{den} = \prod c_v!)。

    分组处理 将在 [l,r][l, r] 内的数字按出现次数分组,记作 (val,cnt)(\text{val}, \text{cnt}),表示有 cnt\text{cnt} 个数字当前出现次数为 val\text{val}。另外,统计 [l,r][l, r] 内未出现的数字个数加入组

    批量增加 将分组按 val\text{val} 从小到大排序。每次取出 val\text{val} 最小的组,设其 val=v\text{val}=v,有 cc 个这样的数字。考虑下一个更大的 val\text{val}(记为 nxtnxt),计算差值 d=nxtvd = nxt - v。如果 mm 足够将这 cc 个数字都增加到 nxtnxt,则批量增加:消耗 c×dc \times d 次添加,并将分母乘上 (nxt!v!)c\left( \frac{nxt!}{v!} \right)^c。如果 mm 不足,则计算最多能将这些数字统一增加到某个值 v+tv+t,其中 t=min(d,m/c)t = \min(d, \lfloor m/c \rfloor),消耗 t×ct \times c 次,分母乘上 ((v+t)!v!)c\left( \frac{(v+t)!}{v!} \right)^c,剩余次数 mm 更新为 mt×cm - t \times c。若 t<dt < d,则产生一组新的 (v+t,c)(v+t, c) 重新放入队列。

    计算结果 最终期望轮数为 E=(n+m)!/denE = (n+m)! / \text{den},对 998244353998244353 取模。需要预处理阶乘,并利用快速幂和逆元进行计算。

    复杂度分析 排序初始序列:O(nlogn)O(n \log n)

    分组数量为 O(不同数字个数)O(\text{不同数字个数}),最多 O(n)O(n)

    每次批量增加至少减少一组或消耗大量 mm,总操作次数为 O(组数)O(\text{组数})

    预处理阶乘到 n+mn+mO(n+m)O(n+m)

    总复杂度 O(nlogn+n+m)O(n \log n + n + m),可接受。

    代码说明(关键部分) factorial 函数预处理阶乘表。

    fast_power 和 inverse 用于模意义下的幂运算和逆元。

    主函数 solve 中:

    读入数据,排序初始数组。

    统计出现次数,固定不在 [l,r][l, r] 内的数字贡献。

    收集 [l,r][l, r] 内数字的出现次数,并加入未出现的数字(次数为0)。

    按出现次数分组,用 vector<pair<size_t, size_t>> 存储并排序。

    贪心增加次数,更新分母 den。

    输出 (n+m)! * inv(den) % mod。

    该算法正确实现了贪心策略,能够在给定约束下高效求出最大期望轮数。

    • 1

    信息

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