📜  欧几里得算法(基本和扩展)

📅  最后修改于: 2021-05-06 21:41:20             🧑  作者: Mango

两个数字的GCD是将两个数字相除的最大数字。查找GCD的一种简单方法是分解两个数并乘以公共质数。

GCD

GCD的基本欧几里得算法
该算法基于以下事实。

  • 如果我们从一个较大的数字中减去一个较小的数字(我们减少一个较大的数字),则GCD不会改变。因此,如果我们不断重复减去两个中的较大者,我们将得到GCD。
  • 现在,如果我们除以较小的数字,则不用减法,而是在找到余数0时算法停止。

以下是使用Euclid算法评估gcd的递归函数。

CPP
// C++ program to demonstrate
// Basic Euclidean Algorithm
#include 
using namespace std;
 
// Function to return
// gcd of a and b
int gcd(int a, int b)
{
    if (a == 0)
        return b;
    return gcd(b % a, a);
}
 
// Driver Code
int main()
{
    int a = 10, b = 15;
    cout << "GCD(" << a << ", "
         << b << ") = " << gcd(a, b)
                        << endl;
    a = 35, b = 10;
    cout << "GCD(" << a << ", "
         << b << ") = " << gcd(a, b)
                        << endl;
    a = 31, b = 2;
    cout << "GCD(" << a << ", "
         << b << ") = " << gcd(a, b)
                        << endl;
    return 0;
}
 
// This code is contributed
// by Nimit Garg


C
// C program to demonstrate Basic Euclidean Algorithm
#include 
 
// Function to return gcd of a and b
int gcd(int a, int b)
{
    if (a == 0)
        return b;
    return gcd(b%a, a);
}
 
// Driver program to test above function
int main()
{
    int a = 10, b = 15;
    printf("GCD(%d, %d) = %dn", a, b, gcd(a, b));
    a = 35, b = 10;
    printf("GCD(%d, %d) = %dn", a, b, gcd(a, b));
    a = 31, b = 2;
    printf("GCD(%d, %d) = %dn", a, b, gcd(a, b));
    return 0;
}


Java
// Java program to demonstrate working of extended
// Euclidean Algorithm
 
import java.util.*;
import java.lang.*;
 
class GFG
{
    // extended Euclidean Algorithm
    public static int gcd(int a, int b)
    {
        if (a == 0)
            return b;
         
        return gcd(b%a, a);
    }
 
// Driver Program
    public static void main(String[] args)
    {
        int a = 10, b = 15, g;
        g = gcd(a, b);
        System.out.println("GCD(" + a +  " , " + b+ ") = " + g);
         
        a = 35; b = 10;
        g = gcd(a, b);
        System.out.println("GCD(" + a +  " , " + b+ ") = " + g);
         
        a = 31; b = 2;
        g = gcd(a, b);
        System.out.println("GCD(" + a +  " , " + b+ ") = " + g);
 
    }
}
// Code Contributed by Mohit Gupta_OMG <(0_o)>


Python3
# Python program to demonstrate Basic Euclidean Algorithm
 
 
# Function to return gcd of a and b
def gcd(a, b):
    if a == 0 :
        return b
     
    return gcd(b%a, a)
 
a = 10
b = 15
print("gcd(", a , "," , b, ") = ", gcd(a, b))
 
a = 35
b = 10
print("gcd(", a , "," , b, ") = ", gcd(a, b))
 
a = 31
b = 2
print("gcd(", a , "," , b, ") = ", gcd(a, b))
 
# Code Contributed By Mohit Gupta_OMG <(0_o)>


C#
using System;
 
class GFG
{
    public static int gcd(int a, int b)
    {
        if (a == 0)
            return b;
         
        return gcd(b % a, a);
    }
     
    // Driver Code
    static public void Main ()
    {
        int a = 10, b = 15, g;
        g = gcd(a, b);
        Console.WriteLine("GCD(" + a +
              " , " + b + ") = " + g);
         
        a = 35; b = 10;
        g = gcd(a, b);
        Console.WriteLine("GCD(" + a +
              " , " + b + ") = " + g);
         
        a = 31; b = 2;
        g = gcd(a, b);
        Console.WriteLine("GCD(" + a +
              " , " + b + ") = " + g);
    }
}
 
// This code is contributed by ajit


PHP


Javascript


C++
// C++ program to demonstrate working of
// extended Euclidean Algorithm
#include 
using namespace std;
 
// Function for extended Euclidean Algorithm
int gcdExtended(int a, int b, int *x, int *y)
{
    // Base Case
    if (a == 0)
    {
        *x = 0;
        *y = 1;
        return b;
    }
 
    int x1, y1; // To store results of recursive call
    int gcd = gcdExtended(b%a, a, &x1, &y1);
 
    // Update x and y using results of
    // recursive call
    *x = y1 - (b/a) * x1;
    *y = x1;
 
    return gcd;
}
 
// Driver Code
int main()
{
    int x, y, a = 35, b = 15;
    int g = gcdExtended(a, b, &x, &y);
    cout << "GCD(" << a << ", " << b
         << ") = " << g << endl;
    return 0;
}
 
// This code is contributed by TusharSabhani


C
// C program to demonstrate working of extended
// Euclidean Algorithm
#include 
 
// C function for extended Euclidean Algorithm
int gcdExtended(int a, int b, int *x, int *y)
{
    // Base Case
    if (a == 0)
    {
        *x = 0;
        *y = 1;
        return b;
    }
 
    int x1, y1; // To store results of recursive call
    int gcd = gcdExtended(b%a, a, &x1, &y1);
 
    // Update x and y using results of recursive
    // call
    *x = y1 - (b/a) * x1;
    *y = x1;
 
    return gcd;
}
 
// Driver Program
int main()
{
    int x, y;
    int a = 35, b = 15;
    int g = gcdExtended(a, b, &x, &y);
    printf("gcd(%d, %d) = %d", a, b, g);
    return 0;
}


Java
// Java program to demonstrate working of extended
// Euclidean Algorithm
 
import java.util.*;
import java.lang.*;
 
class GFG
{
    // extended Euclidean Algorithm
    public static int gcdExtended(int a, int b, int x, int y)
    {
        // Base Case
        if (a == 0)
        {
            x = 0;
            y = 1;
            return b;
        }
 
        int x1=1, y1=1; // To store results of recursive call
        int gcd = gcdExtended(b%a, a, x1, y1);
 
        // Update x and y using results of recursive
        // call
        x = y1 - (b/a) * x1;
        y = x1;
 
        return gcd;
    }
 
// Driver Program
    public static void main(String[] args)
    {
        int x=1, y=1;
        int a = 35, b = 15;
        int g = gcdExtended(a, b, x, y);
        System.out.print("gcd(" + a +  " , " + b+ ") = " + g);
 
    }
}
// Code Contributed by Mohit Gupta_OMG <(0-o)>


Python3
# Python program to demonstrate working of extended
# Euclidean Algorithm
    
# function for extended Euclidean Algorithm
def gcdExtended(a, b):
 
    # Base Case
    if a == 0 : 
        return b, 0, 1
            
    gcd, x1, y1 = gcdExtended(b%a, a)
    
    # Update x and y using results of recursive
    # call
    x = y1 - (b//a) * x1
    y = x1
    
    return gcd, x, y
     
 
# Driver code
a, b = 35,15
g, x, y = gcdExtended(a, b)
print("gcd(", a , "," , b, ") = ", g)


C#
// C# program to demonstrate working
// of extended Euclidean Algorithm
using System;
 
class GFG
{
     
    // extended Euclidean Algorithm
    public static int gcdExtended(int a, int b,
                                  int x, int y)
    {
        // Base Case
        if (a == 0)
        {
            x = 0;
            y = 1;
            return b;
        }
 
        // To store results of
        // recursive call
        int x1 = 1, y1 = 1;
        int gcd = gcdExtended(b % a, a, x1, y1);
 
        // Update x and y using
        // results of recursive call
        x = y1 - (b / a) * x1;
        y = x1;
 
        return gcd;
    }
     
    // Driver Code
    static public void Main ()
    {
        int x = 1, y = 1;
        int a = 35, b = 15;
        int g = gcdExtended(a, b, x, y);
        Console.WriteLine("gcd(" + a + " , " +
                              b + ") = " + g);
    }
}
 
// This code is contributed by m_kit


PHP


Javascript


输出 :

GCD(10, 15) = 5
GCD(35, 10) = 5
GCD(31, 2) = 1

时间复杂度: O(Log min(a,b))
扩展的欧几里得算法:
扩展的欧几里得算法还找到整数系数x和y,使得:

ax + by = gcd(a, b) 

例子:

Input: a = 30, b = 20
Output: gcd = 10
        x = 1, y = -1
(Note that 30*1 + 20*(-1) = 10)

Input: a = 35, b = 15
Output: gcd = 5
        x = 1, y = -2
(Note that 35*1 + 15*(-2) = 5)

扩展的欧几里得算法使用递归调用gcd(b%a,a)计算的结果来更新gcd(a,b)的结果。令通过递归调用计算的x和y的值分别为x 1和y 1 。使用以下表达式更新x和y。

x = y1 - ⌊b/a⌋ * x1
y = x1

以下是基于以上公式的实现。

C++

// C++ program to demonstrate working of
// extended Euclidean Algorithm
#include 
using namespace std;
 
// Function for extended Euclidean Algorithm
int gcdExtended(int a, int b, int *x, int *y)
{
    // Base Case
    if (a == 0)
    {
        *x = 0;
        *y = 1;
        return b;
    }
 
    int x1, y1; // To store results of recursive call
    int gcd = gcdExtended(b%a, a, &x1, &y1);
 
    // Update x and y using results of
    // recursive call
    *x = y1 - (b/a) * x1;
    *y = x1;
 
    return gcd;
}
 
// Driver Code
int main()
{
    int x, y, a = 35, b = 15;
    int g = gcdExtended(a, b, &x, &y);
    cout << "GCD(" << a << ", " << b
         << ") = " << g << endl;
    return 0;
}
 
// This code is contributed by TusharSabhani

C

// C program to demonstrate working of extended
// Euclidean Algorithm
#include 
 
// C function for extended Euclidean Algorithm
int gcdExtended(int a, int b, int *x, int *y)
{
    // Base Case
    if (a == 0)
    {
        *x = 0;
        *y = 1;
        return b;
    }
 
    int x1, y1; // To store results of recursive call
    int gcd = gcdExtended(b%a, a, &x1, &y1);
 
    // Update x and y using results of recursive
    // call
    *x = y1 - (b/a) * x1;
    *y = x1;
 
    return gcd;
}
 
// Driver Program
int main()
{
    int x, y;
    int a = 35, b = 15;
    int g = gcdExtended(a, b, &x, &y);
    printf("gcd(%d, %d) = %d", a, b, g);
    return 0;
}

Java

// Java program to demonstrate working of extended
// Euclidean Algorithm
 
import java.util.*;
import java.lang.*;
 
class GFG
{
    // extended Euclidean Algorithm
    public static int gcdExtended(int a, int b, int x, int y)
    {
        // Base Case
        if (a == 0)
        {
            x = 0;
            y = 1;
            return b;
        }
 
        int x1=1, y1=1; // To store results of recursive call
        int gcd = gcdExtended(b%a, a, x1, y1);
 
        // Update x and y using results of recursive
        // call
        x = y1 - (b/a) * x1;
        y = x1;
 
        return gcd;
    }
 
// Driver Program
    public static void main(String[] args)
    {
        int x=1, y=1;
        int a = 35, b = 15;
        int g = gcdExtended(a, b, x, y);
        System.out.print("gcd(" + a +  " , " + b+ ") = " + g);
 
    }
}
// Code Contributed by Mohit Gupta_OMG <(0-o)>

Python3

# Python program to demonstrate working of extended
# Euclidean Algorithm
    
# function for extended Euclidean Algorithm
def gcdExtended(a, b):
 
    # Base Case
    if a == 0 : 
        return b, 0, 1
            
    gcd, x1, y1 = gcdExtended(b%a, a)
    
    # Update x and y using results of recursive
    # call
    x = y1 - (b//a) * x1
    y = x1
    
    return gcd, x, y
     
 
# Driver code
a, b = 35,15
g, x, y = gcdExtended(a, b)
print("gcd(", a , "," , b, ") = ", g)

C#

// C# program to demonstrate working
// of extended Euclidean Algorithm
using System;
 
class GFG
{
     
    // extended Euclidean Algorithm
    public static int gcdExtended(int a, int b,
                                  int x, int y)
    {
        // Base Case
        if (a == 0)
        {
            x = 0;
            y = 1;
            return b;
        }
 
        // To store results of
        // recursive call
        int x1 = 1, y1 = 1;
        int gcd = gcdExtended(b % a, a, x1, y1);
 
        // Update x and y using
        // results of recursive call
        x = y1 - (b / a) * x1;
        y = x1;
 
        return gcd;
    }
     
    // Driver Code
    static public void Main ()
    {
        int x = 1, y = 1;
        int a = 35, b = 15;
        int g = gcdExtended(a, b, x, y);
        Console.WriteLine("gcd(" + a + " , " +
                              b + ") = " + g);
    }
}
 
// This code is contributed by m_kit

的PHP


Java脚本


输出 :

gcd(35, 15) = 5

扩展算法如何工作?

As seen above, x and y are results for inputs a and b,
   a.x + b.y = gcd                      ----(1)  

And x1 and y1 are results for inputs b%a and a
   (b%a).x1 + a.y1 = gcd   
                    
When we put b%a = (b - (⌊b/a⌋).a) in above, 
we get following. Note that ⌊b/a⌋ is floor(b/a)

   (b - (⌊b/a⌋).a).x1 + a.y1  = gcd

Above equation can also be written as below
   b.x1 + a.(y1 - (⌊b/a⌋).x1) = gcd      ---(2)

After comparing coefficients of 'a' and 'b' in (1) and 
(2), we get following
   x = y1 - ⌊b/a⌋ * x1
   y = x1