CF #505 B Weakened Common Divisor

CF #505 B Weakened Common Divisor

题意:问是否存在一个数,每组数据中都有数据可以整除它,并且这个数要大于1,如果存在多组数据随便输出一个,如果不存在,则输出-1。

这题一看到题目就想质因数分解。。然后写着写着。。很麻烦啊,而且,代码写的很乱,后来大佬提点,可以把一组里的两个数据相乘,然后求所有组数据积的最大公因数GCD,再把GCD质因数分解出最小的质数, GCD不一定使对的, 但是分解出来最小的质数肯定是对的, 但是因为数据太大,不能够打表到2e9,我只打表到2e5,但是对于大于2e5的素数就凉啊,然后,还有很多方面总是没考虑到,然后WA了无数次啊。。

思路:把每组数据的积求其最大公因数,再用质因数分解算出其最小质数。但是还有存在每组数据里两个数都是大于2e5(我打素数表的范围),我就凉了啊,所以添加一个步骤,把第一组数据质因数分解,算出其是否包含大于2e5的素数,如果没有分解完的数为1,则令其为2e9+10,就说明,答案一定是在我的打表范围内,如果不等于1,就是肯定存在大于2e5的素数,那么计算一下,后面的每组数据是否都存在这个因子,计算数量,如果数量等与n,则输出。

AC代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn = 2e5+10;
typedef long long ll;
ll p[maxn],num[maxn],k,a[maxn],b[maxn];

void prime(){
    for(int i = 2; i < maxn; i++){
        if(!num[i]){
            for(ll j = 1LL*i*i; j < maxn; j+=i){
                num[j] = 1;
            }
        }
    }
    k = 0;
    for(int i = 2; i < maxn;i++){
        if(!num[i])
            p[++k] = i;
    }
}

ll gcd(ll a,ll b){
    return b == 0?a:gcd(b, a%b);
}

int main(){
    int n;
    ll x, y, a, b, sa, sb;
    prime();
    while(scanf("%d",&n)!=EOF){
        scanf("%lld%lld",&x,&y);
        num[1] = x*y;
        if(n == 1){    //n等于1的时候先输出
            printf("%lld\n",x);
            continue;
        }
        for(int i = 1; i <= k&& x >= p[i]; i++){   //判断x中是否存在大于2e5的素数
            while(x % p[i] == 0){
                x /= p[i];
            }
        }
        if(x == 1)
            a = 2e9+10;
        else
            a = x;
        for(int i = 1; i <= k&& y >= p[i]; i++){   //y与x 同理
            while(y % p[i] == 0){
                y /= p[i];
            }
        }
        if(y == 1)
            b = 2e9+10;
        else
            b = y;
        sa = sb = 1;
        for(int i = 2; i <= n; i++){
            scanf("%lld%lld",&x,&y);
            num[i] = x*y;
            if(x % a == 0 || y % a == 0)
                sa++;
            if(y % b == 0|| x % b == 0)
                sb++;
        }
        if(sa == n){
            printf("%lld\n",a);
            continue;
        }
        else if(sb == n){
            printf("%lld\n",b);
            continue;
        }
        ll Gcd = num[1];
        for(int i = 2; i <= n; i++)
            Gcd = gcd(num[i],Gcd);
        int ans = 0;
        for(int i = 1; i <= k;i++){
            if(Gcd % p[i] == 0){
                ans = p[i];
                break;
            }

        }
        if(ans == 0 && Gcd != 1)
            printf("%lld\n",Gcd);
        else if(ans == 0 && Gcd == 1)
            printf("-1\n");
        else
            printf("%d\n",ans);
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值