Codeforces851D Arpa and a list of numbers(素数筛)

来源:互联网 发布:外汇高盛软件 编辑:程序博客网 时间:2024/06/14 21:30
/*素数筛有n个数,可以进行两种操作:1,删除一个数,花费x2,某个数的值+1,花费y现在想让序列所有数的gcd>1,求最小花费。(全部删除也合法)枚举数列中所有的素数i,如果某个数a[j]不是i的倍数,将其删除花费为v1=x,增加到是i倍数花费为v2=(i-a[j]%i)*y;(n-cnt)*x删除所有数,(n-cnt)*y,所有数+1*/#include <iostream>#include <cstring>#include <algorithm>using namespace std;typedef long long LL;const int maxn=1e6+5;int n;LL x,y;int a[maxn];LL sum[maxn];bool is_prime[maxn];//i是否为素数void init()//初始化{    memset(is_prime,0,sizeof(is_prime));    for(int i=2;i<maxn;i++) is_prime[i]=1;}int main(){    ios::sync_with_stdio(false);    while(cin>>n)    {        cin>>x>>y;        memset(sum,0,sizeof(sum));//某个数的个数        for(int i=0; i<n; i++)        {            cin>>a[i];            sum[a[i]]++;        }        LL ans=(LL)n*x;//删除所有的数        LL cnt;        init();        for (int i=2;i<maxn;i++)//枚举素数,改数不进行操作        {            if(is_prime[i])            {                cnt=sum[i];//i以及i的倍数的个数                for(int j=i+i;j<maxn;j+=i)//素数筛法                {                    cnt+=sum[j];                    is_prime[j]=0;                }                if((n-cnt)*min(x,y)<ans)//可能有更小答案                {                    LL ret=0;                    for(int j=0;j<n;j++)                    {                        if(a[j]%i!=0)                        {                            LL v1=x;//删除                            LL v2=(i-a[j]%i)*y;//增加成i的倍数                            ret+=min(v1,v2);                        }                    }                    ans=min(ans,ret);//更新答案                }            }        }        cout<<ans<<endl;    }    return 0;}
阅读全文
0 0