Codeforces Round #432 (Div. 2) D - Arpa and a list of numbers

题意 : 

给出n个数,以及x,y。现在你可以对这n个数进行两种操作。

  1. 把任意一个数删除,花费为x。
  2. 把任意一个数加一,花费为y。

现在要求操作后所有数gcd不为1(不互质),求最小花费。

题解 : 这个题我们要考虑调和级数,怎么做呢,我们考虑最大公因数只可能是某个素数,如果不是素数,那么这个数一定不会最优的。这里面有一个套路。因为注意到 ai 的范围只有 1e6 的大小,所以我们就可以打一个1e6的素数表,然后暴力枚举每一个可能成为 gcd 的数枚举这个数。然后通过x,y去判断一个区间哪些数应该删掉,哪些数应该通过 + 1 变成这个数的倍数,这样的话 我们就可以预处理出 小于等于这个数的出现次数和小于等于这个数的所有数的和。然后就可以 O (1) 的时间找出这个区间内数的代价。

#include<stdio.h>  
#include<algorithm>  
using namespace std;  
#define LL long long  
LL cnt[2000025], pre[2000025];  
int main(void)  
{  
    LL temp, x, y, ans;  
    int n, i, c, t, d, st;  
    scanf("%d%lld%lld", &n, &x, &y);  
    for(i=1;i<=n;i++)  
    {  
        scanf("%d", &t);  
        cnt[t] ++;  
        pre[t] += t;  
    }  
    ans = x*n;  
    c = x/y;  
    for(i=1;i<=2000005;i++)  
    {  
        cnt[i] += cnt[i-1];  
        pre[i] += pre[i-1];  
    }  
    for(d=2;d<=1000000;d++)  
    {  
        temp = 0;  
        for(i=d;i<2000005;i+=d)  
        {  
            if(i-c>i-d+1)  
                temp += (cnt[i-c-1]-cnt[i-d])*x;  
            st = max(i-c, i-d+1);  
            temp += ((cnt[i-1]-cnt[st-1])*i-(pre[i-1]-pre[st-1]))*y;  
        }  
        ans = min(ans, temp);  
    }  
    printf("%lld\n", ans);  
    return 0;  
}  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值