题解:CF1380G Circular Dungeon

把期望转化为所有起始点出发的价值之和再除以 \(n\),只需要最小化所有方案的价值和。

对于某个确定的 \(k\),我们可以贪心分配假宝箱,假宝箱一定是价值最大的 \(k\) 个。 非常显然,否则可以把一个价值较大的真宝箱和价值较小的假宝箱交换。

每个真宝箱对价值和的贡献,就是它的价值乘它被统计进答案的次数。而一个宝箱被统计进答案的次数,就等价于环上以这个宝箱结尾的最长后缀的长度,使得这个后缀上全是真宝箱

价值越大的宝箱,我们希望它被统计进的次数尽可能少,于是这个问题就变成了普及组的排队接水了。

具体的,对于每个 \(k\),先把最大的 \(k\) 个变成假宝箱,将剩下的真宝箱从大到小排序后,第 \(i\)真宝箱对答案的贡献就是 \(\lceil \frac{i}{k} \rceil \times c_i\)

排序后预处理前缀和,外层枚举 \(k\),里层枚举 \(\lceil \frac{i}{k} \rceil\),不要忘记最后除以方案数 \(n\),总复杂度 \(O(n\log n)\)

完整代码见提交记录

signed main()
{
    rd(n); invn=inv(n);
    For(i,1,n) rd(c[i]);
    sort(c+1,c+1+n,greater<ll>());
    For(i,1,n) qadd(c[i],c[i-1]);

    For(K,1,n){
        ll ans=0ll;
        int num=n-K;
        for(int i=1;i<=(num+K-1)/K;i++){
            int l=(i-1)*K+1+K,r=min(i*K+K,n);
            qadd(ans,(c[r]-c[l-1]+mod)%mod*i%mod);
        }
        ans=ans*invn%mod;
        write(ans),Spc;
    } End;
    return 0;
}
posted @ 2025-03-11 16:54  wanggk  阅读(21)  评论(0)    收藏  举报