luogu 2152

SuperGcd

二进制算法

1. A = B, Gcd(A, B) = A;

2. A,B为偶数,  Gcd(A, B) = 2 * Gcd(A / 2, B / 2);

3. A 为偶数, B 为奇数,Gcd(A, B) = Gcd(A / 2, B);

4. A,B为奇数, Gcd(A, B) = Gcd(A - B, B)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>

using namespace std;
const int N = 2e5 + 10;

int C[N * 2];
char s[N];

struct Node {
    inline void Init(int A[]) {
        scanf("%s", s); int Len = strlen(s); A[0] = Len; for(int i = 1; i <= Len; i ++) A[i] = s[i - 1] - '0';
    }
    inline int Cmp(int A[], int B[]) {
        if(A[0] > B[0]) return 1; if(A[0] < B[0]) return -1;
        for(int i = 1; i <= A[0]; i ++) if(A[i] > B[i]) return 1; else if(A[i] < B[i]) return -1;
        return 0;
    }
    inline void Div(int A[]) {
        int tmp(0), j = 1;
        for(int i = 1; i <= A[0]; i ++) {tmp += A[i]; A[i] = tmp / 2; tmp %= 2; tmp *= 10;}
        for(int i = 1; i <= A[0] && !A[i]; i ++, j = i); A[0] = A[0] - j + 1;
        for(int i = 1; i <= A[0]; i ++) A[i] = A[i + j - 1];
    }
    inline void Minus(int A[], int B[]) {
        for(int i = B[0], j = A[0]; i >= 1; i --, j --) {
            if(A[j] < B[i]) {A[j] += 10; A[j - 1] --;} A[j] -= B[i];
        }
        int j = 1;
        for(int i = 1; i <= A[0] && !A[i]; i ++, j = i); A[0] = A[0] - j + 1;
        for(int i = 1; i <= A[0]; i ++) A[i] = A[i + j - 1];
    }
    int a[N], b[N];
    inline void Mul(int A[], int B[]) {
        memset(C, 0, sizeof C);
        int j = 0; for(int i = A[0]; i >= 1; i --) a[++ j] = A[i];
        j = 0; for(int i = B[0]; i >= 1; i --) b[++ j] = B[i];
        for(int i = 1; i <= A[0]; i ++) {
            int x = 0;
            for(int k = 1; k <= B[0]; k ++) {C[i + k - 1] += a[i] * b[k] + x; x = C[i + k - 1] / 10; C[i + k - 1] %= 10;}
            C[i + B[0]] = x;
        }
        j = A[0] + B[0]; while(!C[j] && j > 1) j --; A[0] = 0;
        for(int i = j; i >= 1; i --) A[++ A[0]] = C[i];
    }
    inline void Out(int A[]) {for(int i = 1; i <= A[0]; i ++) printf("%d", A[i]);}
} Big_num_work;

void Gcd(int A[], int B[], int &tot) {
    int imp = Big_num_work.Cmp(A, B); if(imp == 0) return ; if(imp < 0) {Gcd(B, A, tot); return ;}
    int ta(0), tb(0); if(A[A[0]] % 2 == 0) Big_num_work.Div(A), ta = 1; if(B[B[0]] % 2 == 0) Big_num_work.Div(B), tb = 1;
    if(ta && tb) Gcd(A, B, ++ tot);
    else if(!ta && !tb) {Big_num_work.Minus(A, B); Gcd(A, B, tot);}
    else Gcd(A, B, tot);
}

int A[N], B[N], F[N];

int main() {
    Big_num_work.Init(A); Big_num_work.Init(B);
    int T = 0; Gcd(A, B, T);
    if(T == 0) Big_num_work.Out(A);
    else {
        int Tow[2]; Tow[0] = 1, Tow[1] = 2; F[0] = F[1] = 1; for(int i = 1; i <= T; i ++) Big_num_work.Mul(F, Tow);
        Big_num_work.Mul(A, F); Big_num_work.Out(A);
    }
    return 0;
}

 

posted @ 2018-08-20 10:36  xayata  阅读(90)  评论(0编辑  收藏  举报