Codeforces 1034A Enlarge GCD(素数筛选)

题目链接

题目大意

  删去最少的数使剩下的数的\(gcd\)比原来大。

分析

  既然要比来的的\(gcd\)大,那么一定是在原来\(gcd\)基础上乘上某一个数。而又要删除的数最少,那么考虑乘的这个数为素数时可得最优解,这个素数应该是尽量多的数字的质因子。

具体实现

  将所有数字的\(gcd\)求出来然后除去它,再找一个素数,它是尽量多的数字的质因子就行了。可以先写一个欧拉筛得到每个数的最小质因子,然后质因数分解,让这个数不断的除以自己的最小质因子,再让剩下的数除以自己的最小质因子就行了,这个分解方法比试除法快一些,不过比较占内存,但是题目给的内存还是绰绰有余的。最后统计出出现次数最多的质因子就是我们保留的数字,在它们之外就是应该删除的数字。

const int maxn = 3e5+10;
const int maxn2 = 1.5e7+10;
int arr[maxn], u[maxn2], p[maxn2], cnt[maxn2], n, kase;
void pri() {
    for (int i = 2; i<maxn2; ++i) {
        if (!u[i]) u[i] = p[++kase] = i;
        for (int j = 1; i*p[j]<maxn2; ++j) {
            u[i*p[j]] = p[j];
            if (!(i%p[j])) break;
        }  
    }
}
int main(void) {
    pri();
    scanf("%d", &n);
    int g = 0;
    for (int i = 0; i<n; ++i) {
        scanf("%d", &arr[i]);
        g = __gcd(g, arr[i]);
    }
    int maxx = -1;
    for (int i = 0, x; i<n; ++i) {
        arr[i] /= g;
        while(arr[i]>1) {
            x = u[arr[i]];
            while(x == u[arr[i]]) arr[i] /= x;
            maxx = max(maxx, ++cnt[x]);
        }
    }
    printf("%d\n", ~maxx ? n-maxx : maxx);
    return 0;
}
posted @ 2020-04-28 21:51  shuitiangong  阅读(218)  评论(0编辑  收藏  举报