gcd(歐幾里得算法輾轉相除法):
gcd ( a , b )= d ;
即 d = gcd ( a , b ) = gcd ( b , a mod b );以此式進行遞歸即可。
之前一直愚蠢地以為輾轉相除法輸進去時 a 要大於 b ,現在發現事實上如果 a 小於 b,那第一次就會先交換 a 與 b。

1 #include<stdio.h>
2 #define ll long long
3
4 ll gcd(ll a,ll b){ 5 return b==0?a:gcd(b,a%b); 6 } 7
8 int main(){ 9 ll a,b; 10 while(scanf("%lld%lld",&a,&b)!=EOF){ 11 printf("%lld\n",gcd(a,b)); 12 // printf("%lld\n",a>b?gcd(a,b):gcd(b,a));
13 } 14 return 0; 15 }
在原基礎上改成循環之后的GCD:
1 ll gcd(ll a,ll b){ 2 for(;a>0&&b>0;a>b?a%=b:b%=a); 3 return a+b; 4 }
這個代碼是針對非負數范圍的,但除此之外我還糾結了很久,在非負數的范圍內(long long內)與普通遞歸的gcd對拍並沒有發現問題,一直做題的時候也沒有發現有什么問題,但是刷到一題UVA10325,經測試數據中沒有給0或負數,但是用這個WA用遞歸版的AC,並不知道為什么。
所以……還是庫函數/遞歸保平安吧
拓展歐幾里得:
當 gcd ( a , b )= d 時,求絕對值和最小的 x , y 使得 x * a + y * b = d ;
d = gcd ( a , b ) = gcd ( b , a mod b );
設:
x1 * a + y1 * b = d ; ①
x2 * b + y2 * ( a mod b ) = d ; ②
因為 a mod b = a - ( a / b )* b; ③(除法為整除)
將③代入①整理得:
y2 * a + ( x2 - ( a / b ) * y2 ) * b = d; ④
由①和④整理得:
x1 = y2 ;
y1 = x2 - ( a / b ) * y2;
將此結論代入遞歸函數既得。

1 #include<stdio.h>
2 #define ll long long
3
4 void gcd(ll a,ll b,ll& d,ll& x,ll& y){ 5 if(!b){d=a;x=1;y=0;} 6 else {gcd(b,a%b,d,y,x);y-=x*(a/b);} 7 } 8
9 int main(){ 10 ll a,b,d,x,y; 11 while(scanf("%lld%lld",&a,&b)!=EOF){ 12 gcd(a,b,d,x,y); 13 printf("%lld*%lld+%lld*%lld=%lld\n",a,x,b,y,d); 14 } 15 return 0; 16 }
拓展歐幾里得求逆元:
當 a 與 b 互素時有 gcd ( a , b ) = 1 ;
即得: a * x + b * y = 1;
a * x ≡ 1 ( mod b );
由於 a 與 b 互素,同余式兩邊可以同除 a ,得:
1 * x ≡ 1 / a (mod b);
因此 x 是 a mod b 的逆元;
遞歸方法計算:

1 #include<stdio.h> 2 #define ll long long 3 4 ll gcd(ll a,ll b,ll &d,ll& x,ll& y){ 5 if(!b){ 6 d=a; 7 x=1; 8 y=0; 9 return x; 10 } 11 else{ 12 gcd(b,a%b,d,y,x); 13 y-=x*(a/b); 14 } 15 return x; 16 } 17 18 int main(){ 19 ll a,b,d,x,y; 20 while(scanf("%lld%lld",&a,&b)!=EOF){ 21 x=gcd(a,b,d,x,y); 22 printf("a:%lld->x:%lld\n",a,x); 23 // printf("a:%lld->x:%lld\nb:%lld->y:%lld\n",a,x,b,y); 24 } 25 return 0; 26 }
循環方法計算:

1 #include<stdio.h> 2 3 int main(){ 4 int a,b; 5 while(scanf("%d%d",&a,&b)!=EOF){ 6 int x=1,y=0,t; 7 8 { 9 if(a!=1&&b!=1){ 10 int b0=b,q; 11 while(a>1){ 12 q=a/b0; 13 t=b0;b0=a%b0;a=t; 14 t=y;y=x-q*y;x=t; 15 } 16 if(x<0)x+=b; 17 } 18 } 19 20 printf("a:%d->x:%d\n",a,x); 21 } 22 return 0; 23 }
1 ll gcd(ll a,ll b){ 2 if(a!=1&&b!=1){ 3 int b0=b,q,t,x=1,y=0; 4 while(a>1){ 5 q=a/b0; 6 t=b0;b0=a%b0;a=t; 7 t=y;y=x-q*y;x=t; 8 } 9 if(x<0)x+=b; 10 } 11 return x; 12 }