Description
Sheng bill有着惊人的心算能力,甚至能用大脑计算出两个巨大的数的GCD(最大公约 数)!因此他经常和别人比赛计算GCD。有一天Sheng bill很嚣张地找到了你,并要求和你比 赛,但是输给Sheng bill岂不是很丢脸!所以你决定写一个程序来教训他。
Input
共两行: 第一行:一个数A。 第二行:一个数B。0<A,B≤1010000
Output
一行,表示A和B的最大公约数。
Stein算法+高精度压位
首先不断约去A,B的公因数2直至A或B为奇数,记录约去2的次数k。
循环执行:{
若A或B为偶数则不断约去2
若A<B则交换A,B
A-=B
若A=0则输出B*2k,算法结束
}
#include<cstdio> #include<cstring> #define B 1000000000 const int B9=B-1; char s[10010]; struct num{ int a[1200]; int l; num(){l=0;} inline void div2(){ for(int i=l;i>0;i--){ if(a[i]&1)a[i-1]+=B; a[i]>>=1; } a[0]>>=1; while(l&&!a[l])--l; } inline void mut2(){ for(int i=0;i<=l;i++)a[i]<<=1; for(int i=0;i<=l;i++)a[i+1]+=a[i]/B,a[i]%=B; if(a[l+1])l++; } void print(){ printf("%d",a[l]); for(int i=l-1;i>=0;i--)printf("%09d",a[i]); } }a1,b1; inline bool operator<(num&a,num&b){ for(int i=a.l<b.l?b.l:a.l;i>=0;i--){ if(a.a[i]<b.a[i])return true; if(a.a[i]>b.a[i])return false; } return false; } inline bool operator-=(num&a,num&b){ a.a[0]+=1; for(int i=a.l;i>=0;i--)a.a[i]+=B9-b.a[i]; for(int i=0;i<a.l;i++)a.a[i+1]+=a.a[i]/B,a.a[i]%=B; a.a[a.l]%=B; while(a.l&&!a.a[a.l])--a.l; } num*a=&a1,*b=&b1,*c; int t2=0,l; int p10[]={1,10,100,1000,10000,100000,1000000,10000000,100000000}; int main(){ scanf("%s",s); l=strlen(s)-1; for(int i=0;i<=l;i++)a->a[(l-i)/9]+=p10[(l-i)%9]*(s[i]-'0'); a->l=l/9; if(a->a[a->l+1])a->l++; scanf("%s",s); l=strlen(s)-1; for(int i=0;i<=l;i++)b->a[(l-i)/9]+=p10[(l-i)%9]*(s[i]-'0'); b->l=l/9; if(b->a[b->l+1])b->l++; while(!(a->a[0]&1)&&!(b->a[0]&1)){ t2++; a->div2(); b->div2(); } do{ while(!(a->a[0]&1))a->div2(); while(!(b->a[0]&1))b->div2(); if(*a<*b)c=a,a=b,b=c; *a-=*b; }while(a->l!=0||a->a[0]!=0); while(t2--)b->mut2(); b->print(); return 0; }