zoukankan      html  css  js  c++  java
  • CF #505 B Weakened Common Divisor(数论)题解

    题意:给你n组,每组两个数字,要你给出一个数,要求这个是每一组其中一个数的因数(非1),给出任意满足的一个数,不存在则输出-1。

    思路1:刚开始乱七八糟暴力了一下果断超时,然后想到了把每组两个数相乘,然后求每组的GCD,那么这个GCD就是因数的乘积(如果GCD==1就输出-1)。然后打个2e5的素筛表,然后找到GCD的一个素数因数。做到这里好像没问题了,然而,分分钟会被hack,问题出在哪里了?显然啊,打素数表只用2e5的范围,但是因数还包括自己本身啊!所以一旦GCD大于2e5我们就找不到答案了,那么我用一个set来储存遇到的大于2e5的数,如果素筛没找到,那就去set里遍历就行了。

    思路2:还是那个问题,大于2e5的素数怎么解决。大佬告诉我一个方法,把第一组数据质因数分解,如果分解到最后发现第一组数据的质因数出现了大于2e5的素数,那么就把他存起来,在后面判断。

    混合场很不友好,然而我并没有报名,帮别人掉分(逃

    代码1:

    #include<stack>
    #include<vector>
    #include<queue>
    #include<set>
    #include<cstring>
    #include<string>
    #include<sstream>
    #include<iostream>
    #include<algorithm>
    #define ll long long
    #define ull unsigned long long
    using namespace std;
    const int maxn = 2e5+13;
    const int seed = 131;
    const int MOD = 100013;
    const int INF = 0x3f3f3f3f;
    int pr[maxn],p[maxn],pn;
    set<ll> st;
    void get(){
        pn = 0;
        memset(pr,0,sizeof(pr));
        for(int i = 2;i < maxn;i++){
            if(!pr[i]){
                p[pn++] = i;
                for(ll j = (ll) i * i;j < maxn;j += i){
                    pr[j] = 1;
                }
            }
        }
    }
    ull gcd(ull a,ull b){
        return b == 0? a : gcd(b,a % b);
    }
    int main(){
        int n;
        get();
        st.clear();
        scanf("%d",&n);
        ull u,v;
        scanf("%lld%lld",&u,&v);
        if(u >= maxn) st.insert(u);
        if(v >= maxn) st.insert(v);
        ull GCD = u*v;
        bool flag = true;
        for(int i = 2;i <= n;i++){
            scanf("%lld%lld",&u,&v);
            if(u >= maxn) st.insert(u);
            if(v >= maxn) st.insert(v);
            GCD = gcd(GCD,u * v);
            if(GCD == 1){
                flag = false;
                break;
            }
        }
        if(flag){
            for(int i = 0;i < pn && p[i] * p[i] <= GCD;i++){
                if(GCD % p[i] == 0){
                    printf("%d
    ",p[i]);
                    return 0;
                }
            }
            for(set<ll>::iterator it = st.begin(); it != st.end();++it){
                ll u = *it;
                if(GCD % u == 0){
                    printf("%lld
    ",*it);
                    return 0;
                }
            }
            printf("%lld
    ",GCD);
        }
        else printf("-1
    ");
        return 0;
    }

    代码2:

    /*
    author :竹攸
    */
    #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
    ",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
    ",a);
                continue;
            }
            else if(sb == n){
                printf("%lld
    ",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
    ",Gcd);
            else if(ans == 0 && Gcd == 1)
                printf("-1
    ");
            else
                printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    查找质数的算法优化版
    一些新闻链接
    spring的自动装配基础
    Spring中的Autowired注解和Resource注解的区别
    动态规划:01背包 复习
    贪心问题 POJ 2393 Yogurt factory
    穷竭搜索:POJ 3187 Backward Digit Sums
    穷竭搜索: POJ 2718 Smallest Difference
    何凯文每日一句打卡||DAY1~DAY3
    贪心问题:区间覆盖 POJ 1328 Rader Installation
  • 原文地址:https://www.cnblogs.com/KirinSB/p/9507743.html
Copyright © 2011-2022 走看看