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; }