CodeForces 1047C Enlarge GCD(数论)题解

题意:n个数的gcd是k,要你删掉最少的数使得删完后的数组的gcd > k

思路:先求出k,然后每个数除以k。然后找出出现次数最多的质因数即可。

代码:

#include<cmath>
#include<set>
#include<map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include <iostream>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 3e5 + 10;
const int M = 1.5 * 1e7 + 10;
const ull seed = 131;
const int INF = 0x3f3f3f3f;
const int MOD = 1e4 + 7;
int gcd(int a, int b){
    return b == 0? a : gcd(b, a % b);
}
int a[maxn];
int p[4000], prime[4000], pn;
int num[M];
void init(){
    pn = 0;
    memset(p, 0, sizeof(p));
    for(int i = 2;  i < 4000; i++){
        if(!p[i]){
            prime[pn++] = i;
        }
        for(ll j = 0; j < pn && i * prime[j] < 4000; j++){
            p[i * prime[j]] = 1;
            if(i % prime[j] == 0) continue;
        }
    }
//    printf("%d\n", pn);
}
int main(){
    int n, need;
    init();
    scanf("%d", &n);
    memset(num, 0, sizeof(num));
    for(int i = 1; i <= n; i++){
        scanf("%d", &a[i]);
        if(i == 1) need = a[i];
        else need = gcd(need, a[i]);
    }
    for(int i = 1 ; i <= n; i++) a[i] /= need;
    int ans = -1;
    for(int i = 1; i <= n; i++){
        for(int j = 0; j < pn && prime[j] * prime[j] <= a[i]; j++){
            if(a[i] % prime[j] == 0){
                num[prime[j]]++;
                ans = max(ans, num[prime[j]]);
                while(a[i] % prime[j] == 0) a[i] /= prime[j];
            }
        }
        if(a[i] > 1){
            num[a[i]]++;
            ans = max(ans, num[a[i]]);
        }
    }
    if(ans == -1) printf("%d\n", ans);
    else printf("%d\n", n - ans);
    return 0;
}
原文地址:https://www.cnblogs.com/KirinSB/p/10919638.html