#20044. [Senoir] Contest 19/8/23/2- Problem B:最大公因数(gcd)

题目传送:错误 - TYWZOJ

题目描述

你有N个正整数,a1,a2……an。 你觉得这N个正整数的最大公因数太小了,于是你想通过删除一些数使得剩下的数的最大公因数变大。 你现在想知道,你最少需要删掉多少个数?

输入格式 

第一行包含一个正整数N。

第二行包含N个正整数,表示a1,a2……an。

输出格式

一行一个正整数,表示最少要删掉的数的个数。

样例

input

4
6 9 15 30

output

2

样例解释

当前的最大公因数是3,删掉6和9之后剩下的数最大公因数是15。

首先搞清楚最大公因数是什么。

我们知道,一个合数可以用他的质因子的乘积表示,最大公因数是几个数共同的因数,即为几个数共有的质因子的乘积。例如9=3*3      15=3*5    9和15共同的质因子只有3,所以最大公因数为3.

按照这个思路,要使最大公因数乘某个质因子(变大),就需要删除没有这个质因子的数。

理清楚思路,然后就很简单了,建一个数组a记录所有质因子出现次数(注意出现次数是指拥有这个因子的数的个数,如分解4,2只能记录一次),然后遍历这个数组,寻找每个元素与n的差距,当a[i]==n时说明所有数字都拥有这个质因数即它是最大公因数的一部分,continue,记录a[i]!=n时的最小gap=n-a[i],答案即为gap.

记录质因数时,我的打法是打了一遍欧拉筛得到质数表一个一个判,质数表筛到sqrt(10^6)就够了但是我因为懒直接筛到了10^6勤奋的同学自己特判剪枝一下

代码如下:

#include <bits/stdc++.h>
using namespace std;
long long prime[1000005];
bool isprime[1000005];
void Euler_sieve(int n) {
    memset(isprime, 1, sizeof(isprime));
    for (int i = 2; i <= n; i++) {
        if (isprime[i] == 1)
            prime[++prime[0]] = i;
        for (int j = 1; j <= prime[0] && i * prime[j] <= n; j++) {
            isprime[i * prime[j]] = false;
            if (i % prime[j] == 0)
                break;
        }
    }
}
long long n, a[1000005], temp;
int main() {
    freopen("gcd.in", "r", stdin);
    freopen("gcd.out", "w", stdout);
    scanf("%lld", &n);
    Euler_sieve(100005);
    for (long long i = 1; i <= n; i++) {
        scanf("%lld", &temp);
        long long cnt = 0;
        while (++cnt) {
            if (temp % prime[cnt] == 0) {
                a[prime[cnt]]++;
                temp = temp / prime[cnt];
            }
            if (prime[cnt] > temp )
                break;
        }
    }
    long long maxx = 0;
    for (long long i = 1; i <= 1000005; i++) {
        if (a[i] != n)
            maxx = max(maxx, a[i]);
    }
    printf("%lld", n-maxx);
    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值