[SDOI2009]SuperGCD

题目描述

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

输入

共两行: 第一行:一个数A。 第二行:一个数B。

输出

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

样例输入

12
54

样例输出

6

提示

对于20%的数据,0 < A , B ≤ 10 ^ 18。

对于100%的数据,0 < A , B ≤ 10 ^ 10000。

高精度+更相减损,高精度练手好题QAQ...


#include <stdio.h>
#include <cstring>
#include <iostream>
using std::swap;
const int BASE = 100000000;
const int MAXN = 10005;
char s[MAXN];
int cnt;
  
  
template<typename _t>
inline _t read(){
    _t x=0,f=1;
    char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch == '-') f=-f;
    for(;isdigit(ch);ch=getchar()) x = x*10+(ch^48);
    return x*f;
}
  
struct bignum{
    long long a[MAXN],len;
    bignum(){memset(a,0,sizeof a);len = 0;}
  
    inline bool operator < (const bignum & b)const{
        if(len != b.len) return len < b.len;
        for(int i  = len;i>=1;i--) if(a[i] != b.a[i]) return a[i] < b.a[i];
        return 0;
    }
  
    inline bool operator == (const bignum & b)const{
        if(len != b.len) return 0;
        for(int i = len;i>=1;i--) if(a[i] != b.a[i]) return 0;
        return 1;
    }
  
    inline bool operator != (const bignum & b)const{return *this == b ? 0:1;}
  
    inline void operator = (const char *x){
        register int tmp=strlen(x),t=1,k=0,js=0;
        for(int i=tmp-1;i>=0;--i){
            k+=t*(x[i]-'0'),t*=10;
            if(t==BASE) t=1,a[++len]=k,k=0;
        }
        if(k) a[++len]=k;
    }
  
    inline bignum operator - (const bignum &c)const{
        bignum ans; ans.len = len; bignum b = *this;
        for(register int i = 1;i<=c.len||i<=len;i++) {
            if(b.a[i] < c.a[i]) -- b.a[i+1] , b.a[i] += BASE;
            ans.a[i] = b.a[i] - c.a[i];
        }
        while(ans.a[ans.len] == 0 && ans.len > 1) -- ans.len;
        return ans;
    }
      
    inline bignum operator / (const int x){
        bignum ans = *this; 
        for(int i = len;i>=1;i--) ans.a[i-1] += ans.a[i] % x * BASE,ans.a[i] /= x;
        while(!ans.a[ans.len] && ans.len > 1) -- ans.len;
        return ans;
    }
  
    inline bignum operator * (const int x){
        bignum ans; ans.len = ++ len;
        for(int i = 1;i<=ans.len;i++) {
            ans.a[i] += a[i] * x; ans.a[i+1] += ans.a[i]/BASE; ans.a[i] %= BASE;
        }
        while(!ans.a[ans.len] && ans.len > 1) -- ans.len;
        return ans;
    }
  
    inline bool Judge(){return a[1] & 1;}
    inline void print(){printf("%lld",a[len]);for(register int i = len-1;i>=1;i--) printf("%08lld",a[i]);printf("\n");}
    inline void in(){scanf("%s",s);*this=s;}
}a,b;
  
inline bool Judge(){
    if(!a.Judge() && !b.Judge()) {a = a / 2,b = b / 2,++ cnt;return 1;}
    if(!a.Judge()) {a = a / 2;return 1;}
    if(!b.Judge()) {b = b / 2;return 1;}
    return 0;
}
  
int main(){
    a.in();b.in();
    while(a != b) {
        while(Judge());
        if(a == b) break;
        if(a<b) swap(a,b);
        a = a - b;
    } register int num1 = cnt / 25, num2 = cnt % 25 , full = 1<<25;
    while(num1) --num1,a = a * full;
    while(num2) --num2,a = a * 2;
    a.print();
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值