bzoj千题计划288:bzoj1876: [SDOI2009]SuperGCD

时间:2021-07-02 19:39:14

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()>)
{
ss=s.substr(,);
a.push_back(ss[]+ss[]*+ss[]*+ss[]*+ss[]*+ss[]*+ss[]*+ss[]*-*);
s=s.substr(,s.size());
}
int b=;
reverse(s.begin(),s.end());
for(int i=;i<s.size();++i) b=b*+s[i]-;
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()-;i>=;--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()&);
} inline bool iszero(bignum a)
{
return a.size()== && !(*a.begin());
} inline void delzero(bignum &a)
{
while(a.size()>)
{
bignum::iterator it=--a.end();
if(*it) break;
a.erase(it);
}
} inline void sub(bignum &a,bignum b)
{
int i;
for(i=;i<b.size();++i)
{
if(a[i]<b[i]) a[i+]--,a[i]+=N;
a[i]-=b[i];
}
while(i<a.size() && a[i]<)
{
a[i]+=N;
++i;
--a[i];
}
delzero(a);
} inline void half(bignum &a)
{
for(int i=a.size()-;i>=;--i)
{
if(a[i]&) a[i-]+=N;
a[i]=a[i]>>;
}
delzero(a);
} inline void doubled(bignum &a)
{
for(int i=;i<a.size();++i)
{
a[i]<<=;
if(i> && a[i-]>=N) a[i-]-=N,a[i]++;
}
bignum::iterator it=--a.end();
if(*it>=N) *it-=N,a.push_back();
} inline void output(bignum a)
{
int i=a.size()-;
printf("%d",a[i]);
if(!i) return;
for(--i;i>=;--i) printf("%08d",a[i]);
} int main()
{
bignum a=read(),b=read();
int c=;
while()
{
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 ;
}