【bzoj1876】最大公约数

  • 本文为博主原创,未经许可不得转载

用同余原理的话,高精度取模会爆掉(我说的是代码复杂度

这里介绍更相减损术算法:

(1)若$a$为奇数,$b$为偶数,则$gcd(a,b)=gcd(a,\frac{b}{2})$

(2)若$a$为偶数,$b$为奇数,则$gcd(a,b)=gcd(\frac{a}{2},b)$

(3)若$a,b$都为偶数,则$gcd(a,b)=2gcd(\frac{a}{2},\frac{b}{2})$

(4)若$a,b$都为奇数,则$gcd(a,b)=gcd(a-b,b)$

巧妙避开了高精度除法,至于除2的运算,借位就可以了,代码十分简单

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#include<bits/stdc++.h>
#define FILE "read"
#define MAXN 1255
using namespace std;
typedef long long ll;
const ll BASE=1e8,WIDTH=8;
char readin[MAXN*8];
int cnt=0;
struct bigint{
ll s[MAXN],len;
void init(){memset(s,0,sizeof(s));len=0;}
bigint operator =(ll num){init();while(num){s[++len]=num%BASE;num/=BASE;}return *this;}
bigint operator =(char *str){
init();
ll numlen=strlen(str);len=(numlen+WIDTH-1)/WIDTH;
for(int i=numlen-1,t=0,w;i>=0;--i,w*=10){
if((numlen-i-1)%WIDTH==0) {w=1;++t;}
s[t]+=(str[i]-48)*w;
}
return *this;
}
bool operator <(const bigint &b)const{
if(b.len!=len) return len<b.len;
for(int i=b.len;i>=1;--i)if(s[i]!=b.s[i])return s[i]<b.s[i];
return 0;
}
bool operator ==(const bigint &b)const{return !(b<*this)&&!(*this<b);}
bigint operator +(const bigint &b){
for(int i=1;i<=len;++i){
s[i]+=b.s[i];
if(s[i]>=BASE) {s[i]-=BASE; ++s[i+1];}
}
while(s[len+1]) ++len;
return *this;
}
bigint operator -(const bigint &b){
for(int i=1;i<=len;++i){
s[i]-=b.s[i];
if(s[i]<0) {s[i]+=BASE; --s[i+1];}
}
while(!s[len]&&len) --len;
return *this;
}
void MUL2(){
for(int i=1;i<=len;++i) s[i]*=2; len+=5;
for(int i=1;i<=len;++i){
s[i+1]+=s[i]/BASE;
s[i]%=BASE;
}
while(!s[len]&&len) --len;
}
void DIV2(){
len+=5;
for(int i=len;i>=1;--i){
if(s[i]&1)s[i-1]+=BASE;
s[i]>>=1;
}
while(!s[len]&&len) --len;
}
bool MOD2(){
if(len==0) return 0;
else return s[1]%2;
}
void read(){scanf("%s",readin);*this=readin;}
void print(){
if(len==0) puts("0");
else{
printf("%lld",s[len]);
for(int i=len-1;i>=1;--i)
printf("%08lld",s[i]);
}
printf("\n");
}
}A,B,C;
bigint GCD(bigint A,bigint B){
while(!(A==B)){
if(A<B) swap(A,B);
if(!A.MOD2()&&B.MOD2()) A.DIV2();
else if(A.MOD2()&&!B.MOD2()) B.DIV2();
else if(!A.MOD2()&&!B.MOD2()) ++cnt,A.DIV2(),B.DIV2();
else if(A.MOD2()&&B.MOD2()) A=A-B;
}
return A;
}
int main(){
//freopen(FILE".in","r",stdin);
//freopen(FILE".out","w",stdout);
A.read(); B.read(); C=GCD(A,B);
while(cnt--) C.MUL2();
C.print();
return 0;
}
文章目录
,