zoukankan      html  css  js  c++  java
  • 【前缀和】【枚举倍数】 Codeforces Round #432 (Div. 2, based on IndiaHacks Final Round 2017) D. Arpa and a list of numbers

    题意:给你n个数,一次操作可以选一个数delete,代价为x;或者选一个数+1,代价y。你可以进行这两种操作任意次,让你在最小的代价下,使得所有数的GCD不为1(如果全删光也视作合法)。

    我们从1到max(ai)枚举最后都变成的gcd是多少,假设为g,那么所有数都必须变成一个比g大的最小的g的倍数k·g。枚举k,然后在一个区间[(k-1)*g+1,k*g]里,一定存在一个分界点f,使得小于等于f的数全都删去,因为删除的代价小于把它们都变成kg的代价;大于f的数全都变成kg。因为x<=(kg-ai)*y,所以显然这个分界点是kg-ceil(x/y)。不过分界点不一定落在区间里,要讨论一下。

    要预处理前缀和cnt(i)表示小于等于i的数的个数,sum(i)表示小于等于i的数的和。

    特殊情况:一开始全是1。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    int cnt[2000005],n,x,y,a[500005],N;
    ll sum[2000005],ans=9000000000000000000ll,nowans;
    int main(){
    	//freopen("a.in","r",stdin);
    	scanf("%d%d%d",&n,&x,&y);
    	for(int i=1;i<=n;++i){
    		scanf("%d",&a[i]);
    		++cnt[a[i]];
    		sum[a[i]]+=(ll)a[i];
    	}
    	N=*max_element(a+1,a+n+1);
    	if(N==1){
    		printf("%I64d
    ",(ll)n*(ll)min(x,y));
    		return 0;
    	}
    	for(int i=2;i<=N*2;++i){
    		cnt[i]+=cnt[i-1];
    		sum[i]+=sum[i-1];
    	}
    	for(int i=2;i<=N;++i){
    		nowans=0;
    		for(int j=i;j<=N+i;j+=i){
    			int R=j;
    			int L=R-i+1;
    			int upd=R-(int)(ceil((double)x/(double)y)+0.5);
    			if(upd>=L){
    				nowans+=(ll)x*(ll)(cnt[upd]-cnt[L-1]);
    			}
    			else{
    				upd=L-1;
    			}
    			nowans+=(ll)y*((ll)(cnt[R]-cnt[upd])*(ll)R-(sum[R]-sum[upd]));
    		}
    		ans=min(ans,nowans);
    	}
    	printf("%I64d
    ",ans);
    	return 0;
    }
  • 相关阅读:
    网页添加提示音
    poj 2593和poj 2479
    HDU 1558 Segment set
    Ubuntu中conky的安装配置
    Codeforce C. Buns
    HDU 3952 Fruit Ninja
    IE8,IE9,IE10,FireFox 的CSS HACK
    HDU 1086 You can Solve a Geometry Problem too
    Ubuntu中Cairo Dock安装和设置
    Ubuntu 12.04 中安装和配置 Java JDK(转)
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7478211.html
Copyright © 2011-2022 走看看