1 条题解
-
0
题目大意 给定一个长度为 的初始序列 ,我们可以在其后添加 个属于 的正整数。得到的新序列长度为 ,对其进行 Gobo sort 排序。该算法的期望执行轮数(即步骤 2 的期望执行次数)等于 ,其中 , 是每个数字 在新序列中的出现次数。目标是选择添加的 个数,使得期望轮数最大,并输出对 取模的结果。
问题转化 对于固定的新序列,设不同数字的出现次数分别为 ,则成功概率为 ,期望轮数为 。因此,最大化 等价于最小化 。
初始序列给出了部分数字的出现次数。我们只能向 内的数字添加次数(可以增加已有数字的出现次数,也可以引入新数字)。需要分配 次添加,使得最终的 最小。
贪心策略 考虑每次添加一个数,即让某个数字的出现次数增加 。设当前数字 的出现次数为 ,增加一次后, 会乘以 。为了使乘积增长最慢,每次应选择当前 最小的数字进行增加。这样,乘数 最小,从而整体乘积最小。
如果 内有数字未在初始序列中出现,则它们的出现次数视为 ,同样参与贪心。
具体实现 统计初始出现次数 对初始序列排序,统计每个数字的出现次数。对于在 内的数字,记录它们的出现次数;对于不在 内的数字,它们的出现次数固定,直接将其阶乘乘到分母 中(初始 ,最终 )。
分组处理 将在 内的数字按出现次数分组,记作 ,表示有 个数字当前出现次数为 。另外,统计 内未出现的数字个数加入组
批量增加 将分组按 从小到大排序。每次取出 最小的组,设其 ,有 个这样的数字。考虑下一个更大的 (记为 ),计算差值 。如果 足够将这 个数字都增加到 ,则批量增加:消耗 次添加,并将分母乘上 。如果 不足,则计算最多能将这些数字统一增加到某个值 ,其中 ,消耗 次,分母乘上 ,剩余次数 更新为 。若 ,则产生一组新的 重新放入队列。
计算结果 最终期望轮数为 ,对 取模。需要预处理阶乘,并利用快速幂和逆元进行计算。
复杂度分析 排序初始序列:。
分组数量为 ,最多 。
每次批量增加至少减少一组或消耗大量 ,总操作次数为 。
预处理阶乘到 ,。
总复杂度 ,可接受。
代码说明(关键部分) factorial 函数预处理阶乘表。
fast_power 和 inverse 用于模意义下的幂运算和逆元。
主函数 solve 中:
读入数据,排序初始数组。
统计出现次数,固定不在 内的数字贡献。
收集 内数字的出现次数,并加入未出现的数字(次数为0)。
按出现次数分组,用 vector<pair<size_t, size_t>> 存储并排序。
贪心增加次数,更新分母 den。
输出 (n+m)! * inv(den) % mod。
该算法正确实现了贪心策略,能够在给定约束下高效求出最大期望轮数。
- 1
信息
- ID
- 5973
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者