https://codeforces.ml/contest/1047/problem/C
C. Enlarge GCD
将数组的每个数除以他们的GCD后,将其每个数分解最小质因数,统计每个数的质其最小因数x的个数,放进一个质因数x集合里,再取出质因数x个数最多的数。
即保留的数最多的数,也就是去除的数最少的答案。
分解最小质因数时,只需筛取1到本数开根号的数即可,1.5e7开根号的质数只有500多个,即最后的复杂度可减枝为o(n*500)。
#include <iostream> #include <cmath> #include <map> #include <vector> #include <algorithm> using namespace std; int n,a[300007],tot,prim[1000000],isprim[1000000]; const int N=15000000; map <int,int> ma; int gcd(int x,int y){ return y==0? x:gcd(y,x%y); } void solve(){ for(int i=0;i<=sqrt(N);i++){ isprim[i]=true; } isprim[0]=isprim[1]=0; for(int i=2;i<=sqrt(N);i++){ if(isprim[i]){ prim[++tot]=i; for(int j=i*2;j<=sqrt(N);j+=i){ isprim[j]=false; } } } } int main(){ solve(); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } int gd=a[1]; for(int i=1;i<=n;i++){ gd=gcd(gd,a[i]); } for(int i=1;i<=n;i++){ a[i]=a[i]/gd; } for(int i=1;i<=n;i++){ int now=0; for(int j=1;j<=tot;j++){ while(a[i]%prim[j]==0){ //cout<<i<<" "<<prim[j]<<endl; a[i]/=prim[j]; if(prim[j]==now) continue; ma[prim[j]]++; now=prim[j]; } } if(a[i]!=1){ ma[a[i]]++; } } int ans=0; for(auto it:ma){ ans=max(ans,it.second); } if(ans!=0) cout<<n-ans<<endl; else cout<<"-1"<<endl; }