一本通1627【例 3】最大公约数
1627:【例 3】最大公约数
时间限制: 1000 ms 内存限制: 524288 KB【题目描述】
给出两个正整数 A,B,求它们的最大公约数。
【输入】
输入共两行,第一行一个正整数 A,第二行一个正整数 B。
【输出】
在第一行输出一个整数,表示 A,B 的最大公约数。
【输入样例】
18
24
【输出样例】
6
【提示】
数据范围与提示:
对于 60% 的数据,1≤A,B≤1018;
对于 100% 的数据,1≤A,B≤103000 。
sol:Super Gcd,高精。。。
直接辗转相除肯定优秀到爆炸,所以我们选择辗转相减
然而直接辗转相减肯定也是优秀到爆炸,但是这道题特别水的数据居然让我过了,这还说什么。。。
对于辗转相减有一个优化,就是对于当前两个数,如果一奇一偶,就把偶数除以2,如果两个偶,就都除以2,把答案*2,如果两奇就辗转相减。
#include <bits/stdc++.h> using namespace std; typedef int ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) { f|=(ch=='-'); ch=getchar(); } while(isdigit(ch)) { s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x<10) { putchar(x+'0'); return; } write(x/10); putchar((x%10)+'0'); return; } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar('\n') inline void Read_S(char *S) { int Len=0; char ch=' '; while(!isdigit(ch)) { ch=getchar(); } while(ch=='0') { ch=getchar(); } while(isdigit(ch)) { S[++Len]=ch; ch=getchar(); } return; } const int N=3005; const int Base=10000,Power=4; char SX[N],SY[N]; struct BigNum { int a[N]; BigNum() { memset(a,0,sizeof a); } BigNum(char *S) { memset(a,0,sizeof a); int i,bb,Pos=0,Len=strlen(S+1); a[0]=(Len-1)/Power+1; for(i=1;i<=Len;i++) { if((i-1)%Power==0) { Pos++; bb=1; } a[Pos]+=bb*(S[i]-'0'); bb*=10; } } inline void Print() { write(a[a[0]]); int i; for(i=a[0]-1;i>=1;i--) { if(a[i]<1000) putchar('0'); if(a[i]<100) putchar('0'); if(a[i]<10) putchar('0'); write(a[i]); } } #define P(x) x.Print(),putchar(' ') #define Pl(x) x.Print(),putchar('\n') }X,Y; inline bool operator<(const BigNum &p,const BigNum &q) { if(p.a[0]!=q.a[0]) return p.a[0]<q.a[0]; int i; for(i=p.a[0];i>=1;i--) if(p.a[i]!=q.a[i]) { return p.a[i]<q.a[i]; } return false; } inline bool operator==(const BigNum &p,const BigNum &q) { if(p.a[0]!=q.a[0]) return false; int i; for(i=p.a[0];i>=1;i--) if(p.a[i]!=q.a[i]) { return false; } return true; } inline BigNum operator-(const BigNum &p,const BigNum &q) { int i; BigNum ans=p; for(i=1;i<=q.a[0];i++) { ans.a[i]-=q.a[i]; if(ans.a[i]<0) { ans.a[i]+=Base; ans.a[i+1]--; } } while((!ans.a[ans.a[0]])&&ans.a[0]) ans.a[0]--; return ans; } int main() { freopen("data.in","r",stdin); freopen("my.out","w",stdout); Read_S(SX); reverse(SX+1,SX+strlen(SX+1)+1); X=BigNum(SX); Read_S(SY); reverse(SY+1,SY+strlen(SY+1)+1); Y=BigNum(SY); while(!(X==Y)) { BigNum p,q; if(X<Y) { p=Y; q=X; } else { p=X; q=Y; } X=q; Y=p-q; } Pl(X); return 0; }
#include <bits/stdc++.h> using namespace std; typedef int ll; inline ll read() { ll s=0; bool f=0; char ch=' '; while(!isdigit(ch)) { f|=(ch=='-'); ch=getchar(); } while(isdigit(ch)) { s=(s<<3)+(s<<1)+(ch^48); ch=getchar(); } return (f)?(-s):(s); } #define R(x) x=read() inline void write(ll x) { if(x<0) { putchar('-'); x=-x; } if(x<10) { putchar(x+'0'); return; } write(x/10); putchar((x%10)+'0'); return; } #define W(x) write(x),putchar(' ') #define Wl(x) write(x),putchar('\n') inline void Read_S(char *S) { int Len=0; char ch=' '; while(!isdigit(ch)) { ch=getchar(); } while(ch=='0') { ch=getchar(); } while(isdigit(ch)) { S[++Len]=ch; ch=getchar(); } return; } const int N=3005; const int Base=10000,Power=4; char SX[N],SY[N]; struct BigNum { int a[N]; BigNum() { memset(a,0,sizeof a); } BigNum(char *S) { memset(a,0,sizeof a); int i,bb,Pos=0,Len=strlen(S+1); a[0]=(Len-1)/Power+1; for(i=1;i<=Len;i++) { if((i-1)%Power==0) { Pos++; bb=1; } a[Pos]+=bb*(S[i]-'0'); bb*=10; } } inline void Print() { write(a[a[0]]); int i; for(i=a[0]-1;i>=1;i--) { if(a[i]<1000) putchar('0'); if(a[i]<100) putchar('0'); if(a[i]<10) putchar('0'); write(a[i]); } } #define P(x) x.Print(),putchar(' ') #define Pl(x) x.Print(),putchar('\n') }X,Y,Ans; inline bool operator<(const BigNum &p,const BigNum &q) { if(p.a[0]!=q.a[0]) return p.a[0]<q.a[0]; int i; for(i=p.a[0];i>=1;i--) if(p.a[i]!=q.a[i]) { return p.a[i]<q.a[i]; } return false; } inline bool operator==(const BigNum &p,const BigNum &q) { if(p.a[0]!=q.a[0]) return false; int i; for(i=p.a[0];i>=1;i--) if(p.a[i]!=q.a[i]) { return false; } return true; } inline BigNum operator-(const BigNum &p,const BigNum &q) { int i; BigNum ans=p; for(i=1;i<=q.a[0];i++) { ans.a[i]-=q.a[i]; if(ans.a[i]<0) { ans.a[i]+=Base; ans.a[i+1]--; } } while((!ans.a[ans.a[0]])&&ans.a[0]) ans.a[0]--; return ans; } inline BigNum operator*(const BigNum &p,const BigNum &q) { int i,j; BigNum ans; ans.a[0]=max(p.a[0],q.a[0]); for(i=1;i<=p.a[0];i++) { for(j=1;j<=q.a[0];j++) { ans.a[i+j-1]+=p.a[i]*q.a[j]; ans.a[i+j]+=ans.a[i+j-1]/Base; ans.a[i+j-1]%=Base; } } while(ans.a[ans.a[0]+1]) ans.a[0]++; while(!ans.a[ans.a[0]]) ans.a[0]--; return ans; } inline bool Judge_Ou(BigNum p) { if(!p.a[0]) return 1; return (p.a[1]&1)?0:1; } inline BigNum Div2(BigNum p) { BigNum ans; ans.a[0]=p.a[0]; int i; for(i=p.a[0];i>=1;i--) { ans.a[i]+=(p.a[i]>>1); if(p.a[i]&1) p.a[i-1]+=Base; } while(!ans.a[ans.a[0]]) ans.a[0]--; return ans; } inline BigNum Mul2(BigNum p) { BigNum ans; ans.a[0]=p.a[0]; int i; for(i=1;i<=p.a[0];i++) { p.a[i]<<=1; if(p.a[i]>Base) { ans.a[i+1]+=p.a[i]/Base; p.a[i]%=Base; } ans.a[i]+=p.a[i]; } while(ans.a[ans.a[0]+1]) ans.a[0]++; return ans; } int main() { freopen("data.in","r",stdin); freopen("my.out","w",stdout); Read_S(SX); reverse(SX+1,SX+strlen(SX+1)+1); X=BigNum(SX); Read_S(SY); reverse(SY+1,SY+strlen(SY+1)+1); Y=BigNum(SY); Ans.a[0]=Ans.a[1]=1; while(!(X==Y)) { // P(X); Pl(Y); bool BoX=Judge_Ou(X),BoY=Judge_Ou(Y); if(BoX) { if(BoY) { X=Div2(X); Y=Div2(Y); Ans=Mul2(Ans); } else { X=Div2(X); } } else { if(BoY) { Y=Div2(Y); } else { BigNum p,q; if(X<Y) p=Y,q=X; else p=X,q=Y; X=p-q; Y=q; } } } Ans=Ans*X; Pl(Ans); return 0; }
河田は河田、赤木は赤木……。
私は誰ですか。教えてください、私は誰ですか。
そうだ、俺はあきらめない男、三井寿だ!