/*
素数筛
有n个数,可以进行两种操作:
1,删除一个数,花费x
2,某个数的值+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;
}
Codeforces851D Arpa and a list of numbers(素数筛)
最新推荐文章于 2020-02-13 13:28:48 发布