[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;}
posted @ 2023-08-14 16:29  Zimo_666  阅读(7)  评论(0编辑  收藏  举报