Codeforces Round #511 (Div. 2)

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;
}

  

原文地址:https://www.cnblogs.com/kksk/p/13901479.html