bzoj千题计划288:bzoj1876: [SDOI2009]SuperGCD(压维高精度gcd)
http://www.lydsy.com/JudgeOnline/problem.php?id=1876
高精压位GCD
对于 GCD(a, b) a>b
若 a 为奇数,b 为偶数,GCD(a, b) = GCD(a, b / 2)
若 a 为偶数,b 为奇数,GCD(a, b) = GCD(a / 2, b)
若 a 为偶数,b 为偶数,GCD(a, b) = 2*GCD(a / 2, b / 2)
若 a 为奇数,b 为奇数,GCD(a, b) = GCD(a - b, b)
vector 压8位 是 压4位 用时的一半
vector 写 高精 真心 方便
#include<cstdio> #include<cstring> #include<vector> #include<algorithm> #include<iostream> using namespace std; #define N 100000000 typedef vector<int> bignum; inline bignum read() { bignum a; string s,ss; cin>>s; reverse(s.begin(),s.end()); while(s.size()>8) { ss=s.substr(0,8); a.push_back(ss[0]+ss[1]*10+ss[2]*100+ss[3]*1000+ss[4]*10000+ss[5]*100000+ss[6]*1000000+ss[7]*10000000-48*11111111); s=s.substr(8,s.size()); } int b=0; reverse(s.begin(),s.end()); for(int i=0;i<s.size();++i) b=b*10+s[i]-48; a.push_back(b); return a; } inline bool bigger(bignum a,bignum b) { if(a.size()>b.size()) return true; if(a.size()<b.size()) return false; for(int i=a.size()-1;i>=0;--i) { if(a[i]>b[i]) return true; if(a[i]<b[i]) return false; } return false; } inline bool iseven(bignum a) { return !(*a.begin()&1); } inline bool iszero(bignum a) { return a.size()==1 && !(*a.begin()); } inline void delzero(bignum &a) { while(a.size()>1) { bignum::iterator it=--a.end(); if(*it) break; a.erase(it); } } inline void sub(bignum &a,bignum b) { int i; for(i=0;i<b.size();++i) { if(a[i]<b[i]) a[i+1]--,a[i]+=N; a[i]-=b[i]; } while(i<a.size() && a[i]<0) { a[i]+=N; ++i; --a[i]; } delzero(a); } inline void half(bignum &a) { for(int i=a.size()-1;i>=0;--i) { if(a[i]&1) a[i-1]+=N; a[i]=a[i]>>1; } delzero(a); } inline void doubled(bignum &a) { for(int i=0;i<a.size();++i) { a[i]<<=1; if(i>0 && a[i-1]>=N) a[i-1]-=N,a[i]++; } bignum::iterator it=--a.end(); if(*it>=N) *it-=N,a.push_back(1); } inline void output(bignum a) { int i=a.size()-1; printf("%d",a[i]); if(!i) return; for(--i;i>=0;--i) printf("%08d",a[i]); } int main() { bignum a=read(),b=read(); int c=0; while(1) { if(bigger(b,a)) swap(a,b); if(iszero(b)) break; if(iseven(a) && iseven(b)) { half(a); half(b); c++; } else if(iseven(a)) half(a); else if(iseven(b)) half(b); else sub(a,b); } while(c--) doubled(a); output(a); return 0; }