Greatest Common Divisor)
Euclidean Algorithm:
Theorem 1: Set A, B, C, and Q to an integer and B> 0. If a = Q B + C, then gcd (a, B) = gcd (B, c)
The proof method uses the set method, that is, the appointment Number of one must be the appointment number of the other, so that two numbers are equal.
With this theorem, we can write Euclidean algorithms.
(1) iterative version
Int ITERATIVE-GCD (int A, int B) {<br/> int r = A % B; <br/> while (r) {<br/> A = B; <br/> B = r; <br/> r = A % B; <br/>}< br/> return B; <br/>}
(2) recursive version
Int RECURSIVE-GCD (int A, int B) {<br/> If (B = 0) return a; else return RECURSIVE-GCD (B, A % B); <br/>}
Obviously, recursion is easier to write than iteration, and it is not easy to make mistakes. But is the efficiency much worse?
Theorem 2(Proved by French mathematician lamee) the Division times required by the Euclidean algorithm shall not exceed 5 times the decimal digits of the smaller numbers in M and N.
Theorem 3:(Slight weakness )...... No more than 2 logs (n + 1), where N is a small number
With the above theorem, I have reason to believe in the advantages of recursive versions, but both of them are required!
Extended Euclidean Algorithm (Extended Euclidean Algorithm)
Can be usedInteger Solution of a binary system
Ax + by = M. gcd (a, B) = 1 is required. Otherwise, the two sides are divided by GCD, and the final result is multiplied by GCD.
(3) iterative Extended Euclidean Algorithm
# Include <stdio. h> <br/> int extended_euclidean (int n, int M, Int & X, Int & Y) {<br/> int X1 = 1, X2 = 0, x3 = N; <br/> int Y1 = 0, y2 = 1, Y3 = m; <br/> while (X3% Y3! = 0) {<br/> int d = N/m; <br/> int T1, T2, T3; <br/> T1 = x1-D * Y1; t2 = x2-D * Y2; T3 = X3-D * Y3; <br/> X1 = Y1; x2 = Y2; X3 = Y3; <br/> Y1 = T1; y2 = t2; Y3 = T3; <br/>}; <br/> X = Y1; y = Y2; <br/> return Y3; <br/>}< br/> int main () {<br/> int n, m; <br/> while (scanf ("% d ", & N, & M) = 2) {<br/> int X, Y, gcd; <br/> GCD = extended_euclidean (n, m, x, y ); <br/> printf ("The GCD of % d and % d is % d. /n % d * % d + % d * % d = 1/N ", n, m, gcd, n, x, M, y ); <br/>}< br/> return 0; <br/>}< br/>
(4) recursive Extended Euclidean Algorithm
Int extended_euclidean (int n, int M, Int & X, Int & Y) {<br/> If (M = 0) {<br/> x = 1; y = 0; return N; <br/>}< br/> int G = extended_euclidean (m, n % m, x, y ); <br/> int T = x-N/m * Y; <br/> X = y; <br/> Y = T; <br/> return g; <br/>}
Recursion is easy to write and easy to remember.
Knowing a solution, All Integer Solutions of this equation can be expressed.
X = x0 + B K
Y = y0 + A K
In this way, if the minimum positive integer is required, we can calculate it!
Principle: taken from the Internet
Make a1 = A/gcd (a, B), b1 = B/gcd (a, B), M1 = m/gcd (A, B ). If we can first find the X1 and Y1 that meet the equation A * X1 + B * Y1 = gcd (a, B), then x = x1 * m1, y = Y1 * m1. Due to the Euclidean Algorithm gcd (a, B) = gcd (B, A % B), a * X1 + B * Y1 = gcd (a, B) = gcd (B, A % B) = B * X2 + (a % B) * Y2. Now we only need to perform some deformation to get the formula used in the Extended Euclidean algorithm. So that K = A/B (quotient), r = A % B (remainder), then a = K * B + R. Therefore, r = A-K * B is taken into the upper formula to obtain a * X1 + B * Y1 = B * X2 + (a-(A/B) * B) y2 = A * y2 + B * (x2-(A/B) * Y2) => X1 = Y2, Y1 = x2-(A/B) * Y2. With these two formulas, we can see the change of the corresponding parameters X and Y when we use Euclidean to calculate the maximum common approx. Now, let's look at the code for extending the Euclidean algorithm. In fact, extending the Euclidean algorithm is while finding the maximum common divisor of A and B, the values of a group of X1 and Y1 that meet the equation A * X1 + B * Y1 = gcd (A, B) are also obtained. The highlighted part of the code below is the code of the standard Euclidean algorithm.
Application:
(1) Evaluate the inverse element of a certain prime number
Extended_euclidean (N, P, x, y); <br/> X = x % P; <br/> If (x <0) x + = P; // Since X may be a negative number, We Need To modulo p. </P> <p>
(2)Usaco 4.1 nuggets positive integer solution
Ax + by = C, where gcd (a, B) = 1, a> 0, B> 0; A posivesolution exists if C> = a * B
Proof:
From Extended Euclidean, we know that there exists a solution ax0 + by0 = C
** We want to find XN, YN, where XN> 0, yn> 0. xn = x0 + B * t, yn = y0-A * t;
**-X0/B <= T <= Y0/. For C> = a * B, we know that X0/B + Y0/A> = 1, so it exists
(3) fzu sort l
/******************************** <Br/> ** description: C (n, m) % P (1 <= n <= 10e9, 1 <= m <= 10e4, 1 <= P <= 10e9) <br/> ** algorithm: extended_euclidean <br/> ** Analysis! <Br/> ** time: 18:43:08 <br/> ********************************** /<br/> # include <stdio. h> <br/> long exgcd (long N, long M, long & X, long & Y) {<br/> If (M = 0) {<br/> x = 1; y = 0; return N; <br/>}< br/> long G = exgcd (m, n % m, X, y); <br/> long T = x-N/m * Y; <br/> X = y; <br/> Y = T; <br/> return g; <br/>}< br/> int main () {<br/> long n, m, p, cases; <br/> scanf ("% i64d", & cases); <br/> while (cases --) {<br/> scanf ("% i64d % i64d % i64d ", & N, & M, & P); <br/> long x, y, ANS = 1, I, j; <br/> for (I = n, j = m; j> = 1; I --, j --) {<br/> exgcd (J, P, x, y ); <br/> X = x % P; <br/> If (x <0) x + = P; <br/> ans = (ANS * I) % P; <br/> ans = (ANS * X) % P; <br/>}< br/> printf ("% i64d/N", ANS ); <br/>}< br/>
Note that the intermediate result may exceed int, so long is required.