题解: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;
}

浙公网安备 33010602011771号