[CF1034A] Enlarge GCD
[CF1034A] Enlarge GCD
Description
给一个序列,求最小化删掉多少个数,使得他们的 \(\gcd\) 变大。
Solution
我们首先考虑把所有数先除掉他们的 \(\gcd\),因为 \(\gcd\) 不能影响答案,反而会使值域变大。现在所有数的 \(\gcd\) 都是 \(1\) 了,那么我们考虑把这个值变得大于 \(1\)。
而后我们在值域中筛出所有素数,枚举每个素数,求出每个含有素数倍数个数 \(ans\),答案为 \(n-\max(ans)\)。
如果 \(\max(ans)=0\),输出 -1
。
复杂度 \(O(m\log\log m)\),\(m\) 为筛后的值域。
Code
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+7;
const int M=1.5e7+7;
int a[N],g,prm[M],n,cnt,buc[M],maxx,ans;
bool isprm[M];
void p(int n){
isprm[0]=1,isprm[1]=1;
for(int i=2;i<=n;i++){
if(!isprm[i]) prm[++cnt]=i;
for(int j=1;j<=cnt&&i*prm[j]<=n;j++){
isprm[i*prm[j]]=1;
if(i%prm[j]==0) break;
}
}
}
void solve(){
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]),g=__gcd(a[i],g);
for(int i=1;i<=n;i++) a[i]/=g,maxx=max(a[i],maxx),buc[a[i]]++;
p(maxx);
for(int i=1;i<=cnt;i++){
int res=0;
for(int j=1;prm[i]*j<=maxx;j++) res+=buc[prm[i]*j];
if(res) ans=max(ans,res);
}
printf("%d\n",ans==0?-1:n-ans);
}
int main(){solve();return 0;}