zoukankan      html  css  js  c++  java
  • 【洛谷P2152】SuperGCD【高精度】

    题目大意:

    题目链接:https://www.luogu.org/problemnew/show/P2152
    求两个整数的最大公约数。


    思路:

    神题啊orzorz

    # py3
    import fractions
    print(fractions.gcd(int(input()),int(input())))
    

    本题要用到更相减损法。没有了解过的请自行度娘
    然后利用更相减损法就可以愉快的过掉TT飞。
    例如:

    1 233333333333333333333333333333333333333331 23333333333333333333333333333333333333333
    你需要O(23333333333333333333333333333333333333333)O(23333333333333333333333333333333333333333)才能搞定。

    那么应该怎么样呢?
    可以考虑数的奇偶性。
    设两个数为aabb,那么

    1. aabb都是偶数,那么他们就都有公因子22,于是aabb分别除以22ans×2ans imes 2
    2. aa是偶数,bb是奇数,那么他们肯定没有公因子22,直接aa除以22就可以了。
    3. aa是偶数,bb是奇数,同22
    4. a,ba,b都是奇数,那么直接更相减损即可。

    那么很明显时间复杂度最不优秀的是44,但是奇数-奇数会出现偶数,所以又可以除以22了。

    所以最坏的时间复杂度是O(log max(a,b))O(log max(a,b))


    代码:

    #include <cstdio>
    #include <algorithm>
    #include <iostream>
    #include <cstring>
    using namespace std;
    typedef long long ll;
    
    const int MAXN=1500;
    const ll maxint=1e8;
    int len,sum;
    ll a[MAXN+1],b[MAXN+1];
    char ch[10010];
    
    bool check()
    {
        for (int i=1;i<=MAXN;i++)
            if (b[i]) return 0;
        return 1;
    }
    
    void div2(ll a[])  //除以2
    {
        for (int i=1;i<=MAXN;i++)
        {
            if (a[i]&1) a[i+1]+=maxint;
            a[i]/=2;
        }
    }
    
    void mul2(ll a[])  //乘2
    {
        ll t=0;
        for (int i=MAXN;i>=1;i--)
        {
            a[i]=a[i]*2+t;
            t=a[i]/maxint;
            a[i]%=maxint;
        }
    }
    
    bool check_swap()
    {
        for (int i=1;i<=MAXN;i++)
            if (a[i]>b[i]) return 0;
            else if (b[i]>a[i]) return 1;
        return 0;
    }
    
    void sub(ll a[])  //减法
    {
        for (int i=MAXN;i>=1;i--)
        {
            if (b[i]>a[i])
            {
                a[i-1]--;
                a[i]+=maxint;
            }
            a[i]-=b[i];
        }
    }
    
    int main()
    {
        cin>>ch;
        len=strlen(ch);
        for (int i=1;i<=len;i++)
            a[MAXN-(len-i)/8]=a[MAXN-(len-i)/8]*10+ch[i-1]-48;
        cin>>ch;
        len=strlen(ch);
        for (int i=1;i<=len;i++)
            b[MAXN-(len-i)/8]=b[MAXN-(len-i)/8]*10+ch[i-1]-48;
        if (check_swap()) swap(a,b);
        while (!check())
        {
            if (!(a[MAXN]&1)&&!(b[MAXN]&1))
                div2(a),div2(b),sum++;
            else if (!(a[MAXN]&1))
                div2(a);
            else if (!(b[MAXN]&1))
                div2(b);
            else sub(a);
            if (check_swap()) swap(a,b);
        }
        for (int i=1;i<=sum;i++) 
            mul2(a);
        int i=1;
        while (!a[i]) i++;
        printf("%lld",a[i]);
        for (i++;i<=MAXN;i++)
        {
            if (a[i]<10) putchar(48);
            if (a[i]<100) putchar(48);
            if (a[i]<1000) putchar(48);
            if (a[i]<10000) putchar(48);
            if (a[i]<100000) putchar(48);
            if (a[i]<1000000) putchar(48);
            if (a[i]<10000000) putchar(48);
            printf("%lld",a[i]);
        }
        return 0;
    }
    
  • 相关阅读:
    Python基础语法 第2节课(数据类型转换、运算符、字符串)
    python基础语法 第5节课 ( if 、 for )
    python基础语法 第4节课 (字典 元组 集合)
    Python基础语法 第3节课 (列表)
    A. Peter and Snow Blower 解析(思維、幾何)
    C. Dima and Salad 解析(思維、DP)
    D. Serval and Rooted Tree (樹狀DP)
    C2. Balanced Removals (Harder) (幾何、思維)
    B. Two Fairs 解析(思維、DFS、組合)
    D. Bash and a Tough Math Puzzle 解析(線段樹、數論)
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998406.html
Copyright © 2011-2022 走看看