zoukankan      html  css  js  c++  java
  • P2152 [SDOI2009]SuperGCD

    传送门

    非常显duliu的一道题

    就是求GCD

    因为数据范围...

    所以要上压位高精+非递归的辗转相减

    关于辗转相减:

    如果 A是二的倍数,B是二的倍数   那么GCD(A,B)=2 * GCD(A,B)

    如果只有A是二的倍数   那么GCD(A,B)=GCD(A/2,B)

    如果只有B是二的倍数   那么GCD(A,B)=GCD(A,B/2)

    十分显然的结论...

    然后不停地让大的数减去小的数

    最后当它们相等时就是GCD了(因为大的减小的一直减到不能减就相当于取模)

    int slove()
    {
        int A=read(),B=read(),i=0,j=0;
        while(!(A&1)) A>>=1,i++;
        while(!(B&1)) B>>=1,j++;
        //先把A,B都除成奇数
        //这样之后辗转相减时就不会出现两个数都是偶数的情况了
        //可以减少判断次数
        int cnt=min(i,j);
        while(233)
        {
            if(A<B) swap(A,B);
            if(A==B) return A<<cnt;
            A=A-B;
            while(!(A&1)) A>>=1;
        }
    }
    普通的辗转相减法

    然后就是恶心的压位高精了...

    可以发现我们高精乘除都只乘除2,所以只要写高精乘2和高精除2以及高精减法就好了

    重载运算符和压位都是基本操作了

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    const ll wid=100000000;
    char ch[20007];
    struct bigint
    {
        ll s[1257],len;
        bigint() { memset(s,0,sizeof(s)); len=0; }
        inline void read()
        {
            scanf("%s",ch+1);
            int l=strlen(ch+1),t=0,k=1; len=(l+7)/8;
            for(int i=l;i;i--)
            {
                if(!(l-i)%8){ k=1; t++; }
                s[t]+=k*(ch[i]^48); k*=10;
            }
        }
        inline void print()
        {
            if(!len) { printf("0
    "); return; }
            printf("%lld",s[len]);
            for(int i=len-1;i;i--) printf("%08lld",s[i]);//除了第一位不足的位用0补
            printf("
    ");
        }
        inline bool operator < (const bigint &tmp) const {
            if(len!=tmp.len) return len<tmp.len;
            for(int i=tmp.len;i;i--) if(s[i]!=tmp.s[i]) return s[i]<tmp.s[i];
            return 0;
        }
        inline bool operator == (const bigint &tmp) const {
            return !(tmp<*this)&&!(*this<tmp);
        }
        inline bigint operator - (const bigint &tmp) const {
            bigint u; u.len=len;
            for(int i=1;i<=len;i++)
            {
                u.s[i]+=s[i]-tmp.s[i];
                if(u.s[i]<0) u.s[i]+=wid,u.s[i+1]--;
            }
            while(!u.s[u.len]&&u.len) u.len--;
            return u;
        }
        inline bool pd(){ return s[1]&1; }//判断奇偶
        inline void div2()//除2
        {
            len+=2;
            for(int i=len;i;i--)
            {
                if(s[i]&1) s[i-1]+=wid;
                s[i]>>=1;
            }
            while(!s[len]&&len) len--;
        }
        inline void mul2()//乘2
        {
            for(int i=1;i<=len;i++) s[i]*=2;
            len+=2;
            for(int i=1;i<=len;i++)
            {
                s[i+1]+=s[i]/wid;
                s[i]%=wid;
            }
            while(!s[len]&&len) len--;
        }
    }a,b;
    
    void slove()
    {
        int i=0,j=0;
        while(!a.pd()) a.div2(),i++;
        while(!b.pd()) b.div2(),j++;
        if(i>j) i=j;
        while(1)
        {
            if(a<b) swap(a,b);
            if(a==b) break;
            a=a-b;
            while(!a.pd()) a.div2();
        }
        for(int k=1;k<=i;k++) a.mul2();
        a.print();
    }
    
    int main()
    {
        a.read(); b.read();
        slove();
        return 0;
    }
  • 相关阅读:
    analysis of algorithms
    Measurement of Reflected Radiation
    lecture 5
    lecture 3
    字符串
    Emission of Radiation辐射发射
    Electromagnetic Radiation(EMR) 电磁辐射
    Linux FTP服务器-VSFTPD虚拟用户配置
    jenkins notes
    python nose使用记录
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9778626.html
Copyright © 2011-2022 走看看