Lonely Mountain Dungeons
这道题目为什么考场上没想出来。。。就是不太相信自己吧,而且有个技巧不太清楚。。哎
很明显的一点是各个种族是分开的,所以我们每个种族单独考虑就好了
假设对于一个种族,我们已经固定了分的组数为\(k\)了,那么肯定是“平均”分到每个组是最好的(这点没办法证明,但是我考场上就是想得这一点啊,要学会相信自己,比较显然吧),按照官方题解的说法,就是

然后就是计算贡献这一点,本来我是想用容斥原理的,但是需要循环,看看官方题解的计算就非常简便,我们要学会(好好想一下整个的时间复杂度)

但是如果\(k>c\)了怎么办?此时,之后的任何一个组数都当前种族的分法都是固定的(让每个人的组别不同),所以贡献也是一样的,此时就要记住官方题解所使用的技巧了,我们用一个数组\(add[i]\)记录下来,最后求出\(add\)数组的前缀和就好了(讨论\(k>c\)的情形对降低时间复杂度非常重要)
update 2024.7.7
其实证明的话,利用反证法+微扰法就可以证明了,也比较easy
然后这一次做我还是没有想到官方题解这种计数方法,主要原因就是计数对象拘泥于每个微观的人,而官方题解是先宏观地将计数对象定为每个组,这种技巧就要记住
当然利用容斥原理卡常也可以做:对第\(i\)类人,当组数\(k\)定后,其对答案的贡献就是$$C_{c_i}^2-(k-c_i\space mod\space k)C_{\lfloor \frac{c_i}{k}\rfloor}^2-(c_i\space mod\space k)C_{\lfloor \frac{c_i}{k}\rfloor+1}^{2} = C_{c_i}^2-kC_{\lfloor \frac{c_i}{k}\rfloor}^2-(c_i\space mod\space k)\lfloor \frac{c_i}{k}\rfloor$$
将所有的\(c\)放入桶中(也就是计数相同\(c\)的个数),然后对于每个\(c\),利用数论分块,在以\(k\)为下标的数组上利用线段树进行维护(数组的值代表对应\(k\),所有\(c\)的贡献),然后计算即可(其实也不用这么麻烦,我们可以像题解一样,对于\(k>c\)的情况单独讨论,于是就可以直接用上面的式子\(O(1)\)计算贡献)
update 2024.8.9
重新做一遍,做出来了
update 2026.3.10
重新做一遍做出来了,但是不是官方题解那种做法。虽然我觉得官方题解的做法更加优美
我的做法经过gpt优化排版之后如下:
题意分析
有 \(n\) 个种族,第 \(i\) 个种族有 \(c_i\) 个生物。
我们要把所有选择参战的生物分到若干个小队中。题目实际上等价于:每个种族的所有生物都参战,因为把某个生物不放入军队不会带来任何好处,只会减少可能产生的贡献。
设军队一共分成 \(k\) 个小队(\(k\ge 1\))。
对于同一种族,若两只生物分属不同小队,则会为总战力贡献 \(b\)。
但总共 \(k\) 个小队会带来额外代价 \((k-1)x\)。
因此,若固定小队总数为 \(k\),总战力可写成
其中 \(f(a,k)\) 表示:一个种族有 \(a\) 只生物时,把它们分到 \(k\) 个小队中,能够产生的“分属不同小队的同种族对数”的最大值。
于是问题转化为两步:
- 求出固定 \(a,k\) 时 \(f(a,k)\);
- 枚举所有可能的 \(k\),取最大值。
一、固定 \(k\) 时单个种族的最优贡献
考虑某个种族有 \(a\) 个生物,总小队数固定为 \(k\)。
设它在各队中的人数分别为 \(s_1,s_2,\dots,s_k\),满足
这个种族贡献的跨队同种族对数为
利用恒等式
可知,在 \(a\) 固定时,要让贡献最大,就等价于让
最小。显然这时应当让各队人数尽量平均。
设
则最优分配是:
- \(r\) 个小队放 \(q+1\) 个;
- \(k-r\) 个小队放 \(q\) 个。
于是单个种族的最大贡献为
这就是按“小队对”直接统计得到的形式。
更简洁的等价形式
也可以从“总对数减去同队对数”来写:
这个种族总共有
对生物,其中同队内的对数为
因此
这个式子通常更容易化简,也更方便后续分析。
特别地,当 \(a\le k\) 时,\(q=0,r=a\),代入后自然有
说明每个生物单独放一个队即可,贡献达到最大。
二、直接枚举 \(k\) 为什么不够
若直接对每个 \(k\) 计算所有种族的贡献,复杂度约为
显然无法通过。
因此要进一步研究:
固定一个种族人数 \(a\),函数 \(f(a,k)\) 随 \(k\) 如何变化?
三、转换对象法:研究单个种族对所有 \(k\) 的贡献
关键观察是:
\(f(a,k)\) 中最重要的量是
而 \(\left\lfloor \frac{a}{k}\right\rfloor\) 在一段连续区间内会保持不变,可以用整除分块处理。
1. 在一个整除分块内,\(f(a,k)\) 是一次函数
设在某一段 \(k\) 的区间内,
固定不变。此时
把它代入上面的简洁式:
展开化简可得
于是,在这整个分块中,\(f(a,k)\) 关于 \(k\) 是一个一次函数。
因此在同一个分块里,\(k\) 每增加 \(1\),贡献增加一个固定值:
这正是本题能够高效求解的核心。
这里gpt是使用的式子,我是直接在脑海里面想的。也可以想出来,但是容易出错,最开始我就有一些少算或者多算的情况,重新算了多次才搞出来正确的式子
2. 整除分块的区间个数是 \(O(\sqrt a)\)
众所周知,对于固定的 \(a\),函数
不同取值的个数是 \(O(\sqrt a)\) 级别。
因此,单个种族只会产生 \(O(\sqrt a)\) 个分块。
这意味着我们可以不逐个计算每个 \(k\),而是对每个分块整体处理。
四、如何维护所有 \(k\) 的答案
设
则总答案为
因为每个 \(f(c_i,k)\) 都是分块线性的,所以 \(S(k)\) 也是分块线性的。
更进一步,我们可以维护相邻两项的差分:
对一个种族 \(a\),若当前分块对应商 \(q\),那么在这个分块内它对 \(\Delta(k)\) 的贡献恒为
于是只要对所有种族的所有整除分块,统计出它们在对应区间内对差分数组的贡献,就可以得到所有 \(S(k)\)。
最后再计算
取最大值即可。
五、为什么只需要枚举到 \(\max c_i\)
设
当 \(k>M\) 时,对于任意种族 \(c_i\le M<k\),都有 \(c_i\le k\),因此
已经达到饱和,不再继续增加。
而此时总惩罚 \((k-1)x\) 仍然会随着 \(k\) 变大而不减。
所以最优解一定出现在
之中,只需在这个范围内枚举。
六、做法总结
对于每个测试用例:
先令
只考虑 \(1\le k\le M\)。
接着对每个种族人数 \(a=c_i\):
- 用整除分块枚举所有使得 \(\left\lfloor a/k\right\rfloor=q\) 不变的区间;
- 在该区间内,这个种族对 \(f(a,k+1)-f(a,k)\) 的贡献恒为\[\frac{q(q+1)}{2} \]
- 把这个常数加到对应区间的差分结构中。
所有种族处理完以后:
- 先求出 \(S(1)\);
- 根据差分依次推出 \(S(2),S(3),\dots,S(M)\);
- 对每个 \(k\) 计算\[\text{ans}(k)=b\cdot S(k)-(k-1)x \]取最大值。
七、复杂度分析
对于一个种族人数 \(a\),整除分块的块数为 \(O(\sqrt a)\)。
因此所有种族总复杂度为
其中 \(M=\max c_i\)。
由于题目保证所有测试用例中
所以这个复杂度是完全可以通过的。
空间复杂度为
八、结论
本题的关键在于:
- 固定小队数 \(k\) 时,单个种族的最优分配一定是尽量平均分配到各队;
- 单个种族的贡献 \(f(a,k)\) 对于 \(k\) 来说不是乱变的,而是在每个整除分块内是一次函数;
- 因此可以通过维护相邻 \(k\) 的差分,在线性扫描 \(k\) 的同时求出所有答案。
这就把一个看似二维的优化问题,转化成了“对每个种族做整除分块、对总答案做差分扫描”的经典做法。

浙公网安备 33010602011771号