Euclidean algorithm

Reprinted from: http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html

Euclidean algorithm, also known as tossing and turning, is used to calculate the greatest common divisor of two integers a and b.

Basic algorithm: set a=qb+r, where a, b, q, r are all integers, then gcd(a,b)=gcd(b,r), that is, gcd(a,b)=gcd(b,a %b).

The first proof:

      a can be expressed as a = kb + r, then r = a mod b

  Assuming that d is a common divisor of a and b, then we have

  d|a, d|b, and r = a - kb, so d|r

  So d is the common divisor of (b, a mod b)

  Suppose d is the common divisor of (b, a mod b), then

  d | b , d |r , but a = kb +r

  So d is also a common divisor of (a,b)

  Therefore, the common divisors of (a, b) and (b, a mod b) are the same, and their greatest common divisors must also be the same. It is proved that

 

The second proof:

    To prove that the Euclidean algorithm is established, that is: gcd(a,b)=gcd(b,r), where gcd means to take the greatest common divisor, r=a mod b
    to prove gcd(a,b)= gcd(b, r)
    Let c be the greatest common divisor of a, b, that is, c=gcd(a, b), then a=mc, b=nc, where m, n are positive integers, and m, n mutually The prime number
    can be known from r= a mod b, r= a- qb where q is a positive integer,
    then r=a-qb=mc-qnc=(m-qn)c
    b=nc,r=(m-qn)c , and n, (m-qn) coprime (assuming n, m-qn are not coprime, then n=xd, m-qn=yd where x, y, d are all positive integers, and d>1
                                                                then a=mc =(qx+y)dc, b=xdc, then the greatest common divisor of a, b becomes dc, which contradicts the premise,
                                                                 so n, m-qn must be relatively prime)
    then gcd(b,r)=c=gcd (a,b)
    proved.

 

Implementation of the algorithm:

The easiest way is to apply a recursive algorithm, the code is as follows:

copy code
1 int gcd(int a,int b)
2 {
3     if(b==0)
4         return a;
5     return 
6         gcd(b,a%b);
7 }
copy code

The code can be optimized as follows:

1 int gcd(int a,int b)
2 {
3     return b ? gcd(b,a%b) : a;
4 }

Of course you can also use iterative form:

 1 int Gcd(int a, int b)
 2 {
 3     while(b != 0)
 4     {
 5       int r = b;
 6       b = a % b;
 7       a = r;
 8     }
 9     return a;
10 }

 

Extended Euclidean Algorithm

Basic algorithm: For non-negative integers a, b that are not exactly 0, gcd(a, b) represents the greatest common divisor of a, b, there must be integer pairs x, y, such that gcd(a, b) = ax+ by.

Proof: Let a>b.

  1, obviously when b=0, gcd(a,b)=a. At this time x=1, y=0;

  2, when ab!=0

  Let ax1+by1=gcd(a,b);

  bx2+(a mod b)y2=gcd(b,a mod b);

  According to the naive Euclidean principle, gcd(a,b)=gcd(b,a mod b);

  Then: ax1+by1=bx2+(a mod b)y2;

  即:ax1+by1=bx2+(a-(a/b)*b)y2=ay2+bx2-(a/b)*by2;

  According to the identity theorem: x1=y2; y1=x2-(a/b)*y2;

     So we get the method to solve x1, y1: the value of x1, y1 is based on x2, y2.

   The above idea is defined by recursion, because gcd's continuous recursive solution must have a time when b=0, so the recursion can end.

 

Extending Euclid's recursive code:


 1 int exgcd(int a,int b,int &x,int &y)
 2 {
 3     if(b==0)
 4     {
 5         x=1;
 6         y=0;
 7         return a;
 8     }
 9     int r=exgcd(b,a%b,x,y);
10     int t=x;
11     x=y;
12     y=t-a/b*y;
13     return r;
14 }
copy code

 Extended Euclidean non-recursive code:


 1 int exgcd(int m,int n,int &x,int &y)
 2 {
 3     int x1,y1,x0,y0;
 4     x0=1; y0=0;
 5     x1=0; y1=1;
 6     x=0; y=1;
 7     int r=m%n;
 8     int q=(m-r)/n;
 9     while(r)
10     {
11         x=x0-q*x1; y=y0-q*y1;
12         x0=x1; y0=y1;
13         x1=x; y1=y;
14         m=n; n=r; r=m%n;
15         q=(m-r)/n;
16     }
17     return n;
18 }

 

The application of extended Euclidean algorithm mainly has the following three aspects:

(1) Solve the indefinite equation;

(2) Solve the modular linear equation (linear congruence equation);

(3) Solve the inverse of the module;

 

(1) Using the extended Euclidean algorithm to solve the indeterminate equation:

  For the indefinite integer equation pa+qb=c, if c mod Gcd(p, q)=0, then the equation has an integer solution, otherwise there is no integer solution.
  The method for finding an integer solution has been listed above. After finding a set of solutions p0,q0 of p * a+q * b = Gcd(p, q), p * a+q * b = Gcd(p, q) The other integer solutions of satisfies:
  p = p0 + b/Gcd(p, q) * t 
  q = q0 - a/Gcd(p, q) * t (where t is any integer)
  As for the integer solutions of pa+qb=c , just multiply each solution of p * a+q * b = Gcd(p, q) by c/Gcd(p, q).

  After finding a set of solutions p0, q0 for p * a+q * b = Gcd(a, b), it should be a set of solutions for p * a+q * b = c p1 = p0*(c/Gcd( a,b)),q1 = q0*(c/Gcd(a,b)),

  Other integer solutions of p * a+q * b = c satisfy:

  p = p1 + b/Gcd(a, b) * t
  q = q1 - a/Gcd(a, b) * t (where t is any integer)
  p and q are all integer solutions of p * a+q * b = c.
For relevant proofs, please refer to: http://www.cnblogs.com/void/archive/2011/04/18/2020357.html
 
Solve the indeterminate equation ax+by=c using the extended Euclidean algorithm;
code show as below:


1  bool linear_equation( int a, int b, int c, int &x, int & y)
 2  {
 3      int d= exgcd(a,b,x,y);
 4      if (c% d)
 5          return  false ;
 6      int k=c/ d;
 7      x*=k; y*=k;     // only one set of solutions is obtained 
8      return  true ;
 9 }

 

(2) The method of solving the modular linear equation with the extended Euclidean algorithm:

    The congruence equation ax≡b (mod n) has a solution for the unknown x if and only if gcd(a,n) | b. And when the equation has a solution, the equation has gcd(a,n) solutions.

    Solving the equation ax≡b (mod n) is equivalent to solving the equation ax+ ny= b, (x, y are integers)

    Let d = gcd(a,n), if the integers x and y satisfy d = ax + ny (from Extended Euclidean). If d|b, then the equation

    a* x0+ n* y0= d, multiply both sides of the equation by b/ d, (because d|b, it can be divided evenly), get a* x0* b/ d+ n* y0* b/ d= b.
    So x= x0* b/ d, y= y0* b/ d is a solution for ax+ ny= b, so x= x0* b/ d is a solution for ax= b (mod n ).

    A solution of ax≡b (mod n) is x0= x* (b/ d ) mod n, and the d solutions of the equation are respectively xi= (x0+ i* (n/ d ))mod n {i= 0. ..d-1}.

    Let ans=x*(b/d), s=n/d;

    The smallest integer solution to the equation ax≡b (mod n) is: (ans%s+s)%s;

    Relevant proof:

    Prove that the equation has a solution: x0 = x'(b/d) mod n;
    by a*x0 = a*x'(b/d) (mod n)
         a*x0 = d (b/d) (mod n) (since ax' = d (mod n))
                 = b (mod n)

    Prove that the equation has d solutions: xi = x0 + i*(n/d) (mod n);
    by a*xi (mod n) = a * (x0 + i*(n/d)) (mod n)
                             = (a*x0+a*i*(n/d)) (mod n)
                             = a * x0 (mod n) (since d | a)
                             = b

     

First look at a simple example:

5x=4(mod3)

Solve for x = 2,5,8,11,14.......

From this, a rule can be found, that is, the interval of the solution is 3.

So how is the solution interval determined?

If you can manage to find the first solution, and find the interval between the solutions, then you can find the solution set of linear equations modulo.

We set the interval between solutions to be dx.

then there is

a*x = b(mod n);

a*(x+dx) = b(mod n);

Subtract the two equations to get:

a*dx(mod n)= 0;

That is to say, a*dx is a multiple of a and a multiple of n at the same time, that is, a*dx is a common multiple of a and n. In order to find dx, we should find the least common multiple of a and n. At this time, the corresponding dx is the smallest.

Let the greatest common divisor of a and n be d, then the least common multiple of a and n is (a*n)/d.

i.e. a*dx = a*n/d;

So dx = n/d.

Therefore, the interval between the solutions is obtained.

    code show as below:



 1 bool modular_linear_equation(int a,int b,int n)
 2 {
 3     int x,y,x0,i;
 4     int d=exgcd(a,n,x,y);
 5     if(b%d)
 6         return false;
 7     x0=x*(b/d)%n;   //特解
 8     for(i=1;i<d;i++)
 9         printf("%d\n",(x0+i*(n/d))%n);
10     return true;
11}

 

(3) Use the Euclidean algorithm to find the inverse of the modulus:

       Congruence equation ax≡b (mod n), if gcd(a,n)==1, the equation has only one solution.

      In this case, if b==1, the congruence equation is ax=1 (mod n ), gcd(a,n)=1.

      At this time, the obtained x is called the inverse of the multiplication modulo n of a.

      For the congruence equation ax= 1(mod n ), the solution of gcd(a,n)= 1 is to solve the equation

      ax+ ny= 1, x, y are integers. This can be solved by the extended Euclidean algorithm, and the only solution to the original congruence equation is x obtained by the extended Euclidean algorithm.

ll exgcd(ll a,ll b,ll &x, ll &y){
	if(b==0){
		x=1;
		y=0;
		return a;
	}
	ll r=exgcd(b,a%b,y,x);
	y-=x*(a/b);
	return r;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325900330&siteId=291194637