zoukankan      html  css  js  c++  java
  • 「BZOJ 1876」「SDOI 2009」SuperGCD「数论」

    题意

    (gcd(a, b)),其中(a,bleq10^{10000})

    题解

    使用( ext{Stein})算法,其原理是不断筛除因子(2)然后使用更相减损法

    如果不筛(2)因子的话复杂度是线性的,比如(a=1,b=10^{10000})

    再证明下更相减损术,即(gcd(a,b)=gcd(a-b,b))

    假设(d=gcd(a,b)),则(a=pd,b=qd)

    根据定义可知(gcd(p,q)=1)

    因此(px+qy=1)存在解(x,y)

    此时(a-b=pd-q-d=(p-q)d,b=qd)

    ((p-q)x+q(x+y)=px+qy=1)

    得到(gcd(p-q,q)=1),根据定义得到(d=gcd(a-b,b))

    注意一下高精要压位,不然常数巨大

    #include <algorithm>
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    using namespace std;
    
    const int base = 1e9;
    const int N = 1e4 + 10;
    
    struct Int {
        int len, n[N / 9 + 10];
        Int() {}
        Int(char * s) {
            int x = strlen(s);
            len = x / 9 + (x % 9 ? 1 : 0);
            int p = x - 1;
            for(int i = 1; i <= len; i ++) {
                n[i] = 0;
                for(int j = min(p, 8); j >= 0; j --)
                    n[i] = n[i] * 10 + (s[p - j] & 15);
                p -= 9;
            }
        }
        bool zero() { return len == 1 && n[1] == 0; }
        bool judge() { return !zero() && 0 == (n[1] & 1); }
        bool operator < (const Int &b) const {
            if(len != b.len) return len < b.len;
            for(int i = len; i >= 1; i --)
                if(n[i] != b.n[i]) return n[i] < b.n[i];
            return 0;
        }
        bool operator -= (const Int &b) {
            for(int i = 1; i <= len; i ++) {
                if(i <= b.len) {
                    n[i] -= b.n[i];
                    if(n[i] < 0) n[i + 1] --, n[i] += base;
                }
            }
            for(; !n[len] && len > 1; len --);
            return zero();
        }
        void div2() {
            for(int i = 1; i <= len; i ++) {
                if(n[i] & 1) n[i - 1] += base >> 1;
                n[i] >>= 1;
            }
            for(; !n[len] && len > 1; len --);
        }
        void operator <<= (const int &x) {
            for(int t = 1; t <= x; t ++) {
                n[len + 1] = 0;
                for(int i = len; i >= 1; i --) {
                    n[i] <<= 1; n[i + 1] += n[i] / base; n[i] %= base;
                }
                if(n[len + 1]) len ++;
            }
            this -> print();
        }
        void print() {
            for(int i = len; i >= 1; i --)
                if(i == len) printf("%d", n[i]);
                else printf("%09d", n[i]);
            printf("
    ");
        }
    } x, y;
    
    int main() {
        static char A[N], B[N];
        scanf("%s %s", A, B);
        x = Int(A), y = Int(B);
        if(x.zero()) return y.print(), 0;
        if(y.zero()) return x.print(), 0;
        int i = 0, j = 0;
        for(; x.judge(); i ++) x.div2();
        for(; y.judge(); j ++) y.div2();
        while(1) {
            if(!(x < y)) {
                if(x -= y) return y <<= min(i, j), 0;
                while(x.judge()) x.div2();
            } else {
                if(y -= x) return x <<= min(i, j), 0;
                while(y.judge()) y.div2();
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    51nod1260
    51nod1327
    51nod1342
    51nod1479
    LOJ6088
    51nod1634
    51nod1778
    JAVA循环结构学校上机经常遇到的几题 笔记
    B. The Number of Products(Codeforces Round #585 (Div. 2))
    A. Yellow Cards ( Codeforces Round #585 (Div. 2) 思维水题
  • 原文地址:https://www.cnblogs.com/hongzy/p/10371845.html
Copyright © 2011-2022 走看看