CodeForces 1047C思维

题意:

​ Mr. F has nn positive integers, a1,a2,…,an.

​ He thinks the greatest common divisor of these integers is too small. So he wants to enlarge it by removing some of the integers.

​ But this problem is too simple for him, so he does not want to do it by himself. If you help him, he will give you some scores in reward.

​ Your task is to calculate the minimum number of integers you need to remove so that the greatest common divisor of the remaining integers is bigger than that of all integers.

Input:

​ The first line contains an integer nn (2≤n≤3⋅10^5) — the number of integers Mr. F has.

​ The second line contains nn integers, a1,a2,…,an (1≤ai≤1.5⋅10^7).

Output:

​ Print an integer — the minimum number of integers you need to remove so that the greatest common divisor of the remaining integers is bigger than that of all integers.

​ You should not remove all of the integers.

​ If there is no solution, print «-1» (without quotes).

Examples

Input

3
1 2 4

Output

1

Input

4
6 9 15 30

Output

2

Input

3
1 1 1

Output

-1

Note

In the first example, the greatest common divisor is 1 in the beginning. You can remove 1 so that the greatest common divisor is enlarged to 2. The answer is 1.

In the second example, the greatest common divisor is 3 in the beginning. You can remove 6 and 9 so that the greatest common divisor is enlarged to 15. There is no solution which removes only one integer. So the answer is 2.

In the third example, there is no solution to enlarge the greatest common divisor. So the answer is −1.

​ 翻译成汉语就是给你n个数,你会得到这n个数的公共gcd,问最少删除几个数,使得删除后的公共gcd比原来的大,如果有输出最少删除数,没有输出-1

思路:

​ 我们知道,一个数val可以写成p1^a1 ✖️p2^a2✖️ …✖️pnan的形式,若每个数中都存在pk1,pk2,且pk1在每个数中最少存在t1次,pk2在每个数中最少存在t2次,那么这n个数的公共gcd为pk1t1✖️pk2^t2

​ 因此,我们想要提高公共gcd的大小,有以下两种办法:

​ 1.对于每个数都存在的素因子,我们去除它最小的幂次方数,如2, 4, 12,它们中都存在素因子2,2中存在1个素因子2,4中存在2个素因子2,12中存在2个素因子2,因此我们只要去掉最小的幂次方的次数,也就是1个素因子2的2,就可以使得gcd变大

​ 2.对于不是每个数都存在的素因子,我们只要去掉存在改素因子的数,就可以使得gcd变大

​ 对于以上两种情况,我们记录一个最小值即可,若最后需要去除n个或者没办法去除,那么就输出-1

代码:

#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <algorithm>
#define d int32_t
#define r return
#define ll int64_t
#define N 15000000
#define NN 1000000
#define mem(a) memset(a, 0, sizeof(a))
#define For(i, star, endd) for(d i = star; i <= endd; i++)
using namespace std;

d book[N + 5];      //book[i]存i的最小素因子在prime中的下角标
d prime[NN + 5];    //存全部素数
d num[NN + 5];      //存该素数在几个数中出现(若个数等于n取答案与numminx[i]的最小值 小于n取答案与n-num[i]的最小值)
d minx[NN + 5];     //该素数在n个数中若出现,存在其中一个数中出现的次数的最小值
d numminx[NN + 5];  //该素数在n个数中若出现且是最小值的个数

void init() {
    mem(book);
    mem(prime);
    mem(num);
    memset(minx, 0x3f3f3f3f, sizeof(minx));
    mem(numminx);
    For(i, 2, N) {
        if (!book[i]) {
            prime[++prime[0]] = i;
            book[i] = prime[0];
        }
        For(j, 1, prime[0]) {
            if (prime[j] * i > N) {
                break;
            }
            book[i * prime[j]] = j;
            if (i % prime[j] == 0) {
                break;
            }
        }
    }
    r;
}

void work(d a) {
    while(a != 1) {
        d aa = a;
        d t = prime[book[a]], inx = 0;
        num[book[a]]++;
        while (a % t == 0) {
            inx ++;
            a /= t;
        }
        if (inx < minx[book[aa]]) {
            minx[book[aa]] = inx;
            numminx[book[aa]] = 1;
        } else if (inx == minx[book[aa]]) {
            numminx[book[aa]] ++;
        }
    }
}

d main()
{
    init();
    d n, a;
    d minn = 0x3f3f3f3f;
    scanf("%d", &n);
    For(i, 1, n) {
        scanf("%d", &a);
        work(a);
    }
    For(i, 1, prime[0]) {
        if(!num[i]) continue;
        if (num[i] == n) {
            minn = min(numminx[i], minn);
        } else {
            minn = min(n - num[i], minn);
        }
    }
    if (minn == 0x3f3f3f3f || minn == 0 || minn == n) printf("-1\n");
    else printf("%d\n", minn);
    r 0;
}

​ 就酱紫~

转载请注明出处!!!

如果有写的不对或者不全面的地方 可通过主页的联系方式进行指正,谢谢

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值