zoukankan      html  css  js  c++  java
  • BZOJ1876 [SDOI2009]SuperGCD 【高精 + GCD优化】

    题目

    Sheng bill有着惊人的心算能力,甚至能用大脑计算出两个巨大的数的GCD(最大公约 数)!因此他经常和别人比
    赛计算GCD。有一天Sheng bill很嚣张地找到了你,并要求和你比 赛,但是输给Sheng bill岂不是很丢脸!所以你
    决定写一个程序来教训他。

    输入格式

    共两行: 第一行:一个数A。 第二行:一个数B。
    0 < A , B ≤ 10 ^ 10000。

    输出格式

    一行,表示A和B的最大公约数。

    输入样例

    12

    54

    输出样例

    6

    题解

    时隔大半年,我回来A这道题啦【当初写的太BUG了】
    求GCD,很容一想到辗转相除,而高精不好操作取模,这就用到了辗转相除法的本质:更相减损法

    GCD(a,b) = GCD(a,a-b) 【a >b】

    然而这样会T,所以我们还要优化:

    GCD(a,b) = 2*GCD(a/2,b/2) 【2|a且2|b】
    GCD(a,b) = GCD(a/2,b) 【2|a】
    GCD(a,b) = GCD(a,b/2) 【2|b】
    GCD(a,b) = GCD(a,a-b) 【a >b】
    加上个压位高精【高精减法,高精除低精,高精乘低精,高精比较】
    就可以A了

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #define LL long long int
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    using namespace std;
    const int maxn = 10005,B = 4,Base = 10000,maxm = 100005,INF = 1000000000;
    struct NUM{
        int s[maxn],len;
        NUM() {memset(s,0,sizeof(s)); len = 0;}
    };
    istream& operator >>(istream& in,NUM& a){
        string s;
        in>>s;
        int temp = 0,t = 1;
        for (int i = s.length() - 1; i >= 0; i--){
            temp = temp + t * (s[i] - '0');
            if (t * 10 == Base) a.s[++a.len] = temp,temp = 0,t = 1;
            else t *= 10;
        }
        if (temp) a.s[++a.len] = temp;
        return in;
    }
    ostream& operator <<(ostream& out,const NUM& a){
        if (!a.len) out<<0;
        else {
            printf("%d",a.s[a.len]);
            for (int i = a.len - 1; i > 0; i--) printf("%04d",a.s[i]);
        }
        return out;
    }
    bool check(const NUM& a){return !(a.s[1] & 1);}
    bool equal(const NUM& a,const NUM& b){
        if (a.len != b.len) return false;
        REP(i,a.len) if (a.s[i] != b.s[i]) return false;
        return true;
    }
    bool operator <(const NUM& a,const NUM& b){
        if (a.len < b.len) return true;
        if (a.len > b.len) return false;
        for (int i = a.len; i > 0; i--){
            if (a.s[i] < b.s[i]) return true;
            if (a.s[i] > b.s[i]) return false;
        }
        return false;
    }
    void Half(NUM& a){
        int carry = 0,temp;
        for (int i = a.len; i > 0; i--){
            temp = (a.s[i] + carry * Base) / 2;
            carry = a.s[i] + carry * Base - temp * 2;
            a.s[i] = temp;
        }
        while (!a.s[a.len]) a.len--;
    }
    void Twice(NUM& a){
        int carry = 0,temp;
        for (int i = 1; i <= a.len; i++){
            temp = a.s[i] * 2 + carry;
            a.s[i] = temp % Base;
            carry = temp / Base;
        }
        while (carry) a.s[++a.len] = carry % Base,carry /= Base;
    }
    NUM operator -(const NUM& a,const NUM& b){
        NUM c; c.len = a.len;
        int carry = 0,temp;
        for (int i = 1; i <= a.len; i++){
            temp = a.s[i] - b.s[i] + carry;
            if (temp < 0) carry = -1,temp += Base;
            else carry = 0;
            c.s[i] = temp;
        }
        while (!c.s[c.len]) c.len--;
        return c;
    }
    int main(){
        NUM A,B; int cnt = 0;
        cin>>A>>B;
        while (!equal(A,B)){
            if (check(A) && check(B)) Half(A),Half(B),cnt++;
            else if (check(A)) Half(A);
            else if (check(B)) Half(B);
            else {
                if (B < A) swap(A,B);
                B = B - A;
            }
        }
        while (cnt--) Twice(A);
        cout<<A<<endl;
        return 0;
    }
    
  • 相关阅读:
    Spring Boot 使用 Dom4j XStream 操作 Xml
    Spring Boot 使用 JAX-WS 调用 WebService 服务
    Spring Boot 使用 CXF 调用 WebService 服务
    Spring Boot 开发 WebService 服务
    Spring Boot 中使用 HttpClient 进行 POST GET PUT DELETE
    Spring Boot Ftp Client 客户端示例支持断点续传
    Spring Boot 发送邮件
    Spring Boot 定时任务 Quartz 使用教程
    Spring Boot 缓存应用 Memcached 入门教程
    ThreadLocal,Java中特殊的线程绑定机制
  • 原文地址:https://www.cnblogs.com/Mychael/p/8282745.html
Copyright © 2011-2022 走看看