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;
    }
    
  • 相关阅读:
    S32K142学习记录_day1
    dsPIC33EP单片机的PPS(外设引脚选择)
    零欧电阻
    MOS管的栅极和源极之间的电阻
    RDLC表格排序设置
    SQL相关
    使用sql的xmlpath可以把xml文件转化为表格
    Visual Studio2017 无法折叠
    使用图形化界面打包自己的类库
    初识NuGet及快速安装使用
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998406.html
Copyright © 2011-2022 走看看