CF#511-C Enlarge GCD(gcd)

题意:给你一个序列,然后求删除几个数之后整个序列的最大公约数增大
思路:1)我们首先要求出这个公共的gcd,然后要使gcd增大1直到到最大的数,然后再统计因子出现的个数,sort用n减去最大
2) 要统计因子,我们还可以使用欧拉筛提前打好素数表,然后把所有数除以gcd剩下的对素数表来求因子个数(每个合数都是某个素数的倍数)
所以我们采用第二种方法,降低复杂度  欧拉筛才O(N)

完整代码:(如果数组大小没有开够给出的可能是WA的结果)

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
const int maxm = 3e5+5;
const int maxn = 1.5e7+5;
int a[maxm+5],vis[maxn+5],p[maxn+5],s[maxn+5];
int cnt;
int gcd(int x,int y){
    return y? gcd(y,x%y) : x;
}
//欧拉筛
void init(){
    int i ,j;
    cnt = 0;
    memset(vis,0,sizeof(0));
    vis[0] = vis[1] = 1;
    for(i=2;i<=maxn;++i)
    {
        if(!vis[i]) vis[i]= p[cnt++]= i;
        for(j=0;j<cnt&&i*p[j]<=maxm;++j){
            vis[i*p[j]] = p[j];//vis[i+p[j]] = 1;
            if(i%p[j]==0) break;
        }
    }
}
int main()
{
    int n,i,j,g,x,ans;
    init();
    scanf("%d",&n);
    g = 0;
    for(i=1;i<=n;++i) {
        scanf("%d",&a[i]);
        g = gcd(g,a[i]);
    }    
    ans = 0;
    for(i =1;i<=n;i++){
        a[i]/= g;//所有a[i]除以共同gcd(然后记录所有因子个数)
        for(j = 0;p[j]*p[j] <= a[i];j++){
            int q = p[j];
            if(a[i]%q ==0) s[q]++;
            while(a[i]%q==0){
                a[i] /= q;
            }  
        }
        if(a[i] != 1) s[a[i]]++;
    }
    ans = n;
    for(int i=2; i<maxn; ++i){
        ans = min(ans, n-s[i]);
    }
    if(ans == n)    ans = -1;
    printf("%d ", ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Tianwell/p/11320374.html