Codeforces 851D. Arpa and a list of numbers

来源:互联网 发布:高分一号数据预处理 编辑:程序博客网 时间:2024/05/21 11:29

题意

一个序列被定义为坏,当且仅当非空且gcd为1.
被定义为好,当且仅当它不是一个坏序列.
给定n(5e5)个数的序列(1e6),x,y(1e9),x表示从序列从删去一个数的代价,y表示让序列中一个数增加1的代价.
求使给定序列变为好序列的最小代价.

解法

总体思路:枚举质数法,枚举从1到1e6的所有质数,分别考虑让每个数加到质数的倍数或者删去.

第一个问题:对于数字a,质数p,是加还是删去.
比较一下:加的代价是(p-a%p)*y,删去的代价是x,设move=ceil(x/y);
则只要a%p在(0,p-move]范围内选择删除,(p-move,p)内选择加.
注意:p-move可能会小于0,这时将其看成0.实际意义是删去的花费远远超过了加的花费.

第二个问题:如何求解.
由上知,我们仅需要知道n/p个长度为p的区间内总代价和.
删除的代价和是 (0,p-move]内数字个数*x,
加的代价和 (p-move,p-1]内(数字个数*p-各数字之和).
需要区间内数字个数与区间内数字之和,可以考虑序列权值化+前缀和

序列权值化:相当于进行一次计数排序,记录从1到n每个数有几个.
前缀和:预处理sum0=0,sumi=sum(i-1)+ai则∑(i=x,y)ai=sumy-sum(x-1);

/* LittleFall : Hello! */#include <bits/stdc++.h>using namespace std;#define M 3000010#define MAXN 1000010int minFactor[M], prime[M], primeNum;void calPrime(){    for (int i = 2; i < MAXN; i++)    {        if (!minFactor[i])        {            prime[primeNum++] = i;            minFactor[i] = primeNum;        }        for (int j = 1; j <= minFactor[i]; j++)        {            int t = i * prime[j - 1];            if (t >= MAXN)break;            minFactor[t] = j;        }    }}long long  a[M], num[M], sum[M];int main(void){    calPrime();    long long n, x, y;    cin >> n >> x >> y;    for(int i = 0; i < n; i++)    {        int tmp;        scanf("%d", &tmp);        a[tmp]++;    }    for(int i = 1; i < M; i++)    {        num[i] = num[i - 1] + a[i];        sum[i] = sum[i - 1] + 1ll * i * a[i];    }    long long ans = LLONG_MAX;    int move = (x + y - 1) / y;    for(int i = 0; i < primeNum; i++)    {        long long tmp = 0;        int p = prime[i];        for(int j = 0; j <= p + MAXN; j += p)        {            tmp += (num[j + max(p - move, 0)] - num[j]) * x;            tmp += ((num[j + p - 1] - num[j + max(p - move , 0)]) * (j + p) - (sum[j + p - 1] - sum[j +  max(p - move, 0)])) * y;        }        if(tmp < ans) ans = tmp;    }    cout << ans << endl;    return 0;}

总结

1.不等式在除法取整时的等价变换.

若a,x,y为整数,
a*x<y的判断条件,与a<ceil(y/x)相同.
a*x>y的判断条件,与a>floor(y/x)相同.
带等于号时,同理.
小于取上整,大于取下整.

2.long long 类型 在计算时的赋值要注意

一个式子的中间运算过程极有可能产生大于int范围的值,包括加法,乘法,移位等等.

其他

将这个问题收录到 六小时也de不出的bug系列中.

阅读全文
0 0