gcd模板(欧几里得与扩展欧几里得、拓展欧几里得求逆元)

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 }
View Code

在原基础上改成循环之后的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 }

 

 

拓展欧几里得:

当 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 }
View Code

 

拓展欧几里得求逆元:

当 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 }
View Code

 

循环方法计算:

 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 }
View Code

 

 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 }

 

你可能感兴趣的:(GC)