zoukankan      html  css  js  c++  java
  • 「CF1380G」 Circular Dungeon

    CF1380G Circular Dungeon

    看懂样例就能做。

    虽然我瞪了 20 分钟 菜是原罪

    首先可以将从每一个点出发所能获得的价值相加,再除以 (n) 就可以得到价值的期望。

    所以问题转化为使从每一个点出发所能获得的价值之和最小。

    有一个显而易见的结论:我们一定会将价值前 (k) 大的宝箱变成假宝箱。

    为了尽可能减小价值之和,这些假宝箱一定不会相邻,于是这 (k) 个假宝箱把这个环分成了 (k) 段。

    为了方便起见,你可以把环断开成链,以某个假宝箱为断点,每一段都是完整的。

    那么问题就变成了将真宝箱分为 (k) 段,使得从每一个点出发所能获得的价值之和最小。

    显然在同一段的点只能获得自己这一段中宝箱的价值。

    考虑在同一段的每个点出发所能获得的总价值,设这一段宝箱中第 (i) 个宝箱的价值为 (v_i)

    则有

    [sum=sum_{i=1}^niv_i ]

    那么显然这一段中的宝箱价值应按照降序排序才能保证总价值最小。

    我们刚才考虑了一段的总价值,现在我们从总体上看,怎样能够使得价值最小?

    注意到每一段的第一个数会对答案产生一次贡献,每一段的第二个数会对答案产生二次贡献,...,也就是说我们需要保证每一段的第一个数尽可能大,这样对答案的贡献才会小。

    即设一共有 (k) 段,我们可以将真宝箱中价值前 (k) 大的宝箱放在每一段的第一个,剩余真宝箱中的前 (k) 大放在每一段的第二个,以此类推,不足 (k) 个可以看作用 (0) 补齐。

    这样这个题就做完了。

    总时间复杂度为 (O(nlog_2n))

    (其实你看我说这么大一堆代码超简单的)

    #include<bits/stdc++.h>
    using namespace std;
    const int p=998244353;
    const int maxn=3e5+5;
    int a[maxn],sum[maxn];
    int ksm(int a,int b,int p){
    	int ans=1;
    	while(b){
    		if(b&1) ans=1ll*ans*a%p;
    		b>>=1,a=1ll*a*a%p;
    	}
    	return ans;
    }
    int main(){
    	ios::sync_with_stdio(0);
    	cin.tie(0),cout.tie(0);
    	int n;cin>>n;
    	for(int i=1;i<=n;++i) cin>>a[i];
    	sort(a+1,a+n+1);
    	reverse(a+1,a+n+1);
    	for(int i=1;i<=n;++i) sum[i]=(sum[i-1]+a[i])%p;
    	int inv=ksm(n,p-2,p);
    	for(int k=1;k<=n;++k){
    		int ans=0;
    		for(int j=0,i=0;i<n;++j,i+=k)
    			ans=(ans+1ll*j*(sum[min(n,i+k)]-sum[i]+p)%p)%p;
    		cout<<1ll*ans*inv%p<<' ';
    	}
    	return 0;
    }
    
  • 相关阅读:
    JQuery源码解读 JQ框架简化( 妙味讲堂
    Mia Fringe官网会员须知
    require.js
    :before与::before的区别
    css----苹果移动端以及小程序滚动模块卡顿的处理
    Vue使用国密SM4加密
    vue + echarts + echarts-gl 实现3D 环状图
    React Hook 初学
    常用阻止默认行为的两种方式
    理解事件触发,事件捕获,事件冒泡
  • 原文地址:https://www.cnblogs.com/HenryHuang-Never-Settle/p/solution-CF1380G.html
Copyright © 2011-2022 走看看