1. 程式人生 > >擴充套件歐幾里得(乘法逆元)

擴充套件歐幾里得(乘法逆元)

百度百科:擴充套件歐幾里得http://baike.baidu.com/link?url=wFOWllqYIDKw1sHLTeJ-MOFHr6RLwP-3RwWroNS5xFpJq-Z3dDj2WcpvyF2dzixgIEM4aRdId3vZsA78w5CkP_

任意整數和0的公約數是該整數的所有約數
它們的最大公約數為該整數本身
因為0被所有非0整數整除,所以任意非零的整數都是0的約數

歐幾里得演算法:

單純求兩個數的最大公約數的程式碼(遞迴求法):

下面的思想是以遞迴定義的,因為 gcd 不斷的遞迴求解一定會有個時候 b=0,所以遞迴可以結束。

#include<iostream>
#include<algorithm>
using namespace std;
int gcd(int a,int b)
{
    if(b==0){
        return a;
    }
    else{
        return gcd(b,a%b);
    }
}
int main()
{
    int a,b;
    while(cin>>a>>b)
    {
        cout<<gcd(a,b)<<endl;
    }
    return 0;
}

擴充套件演算法:

一.在已知a, b求解一組x,y,使它們滿足貝祖等式: ax+by = gcd(a, b) =d(解一定存在,根據數論中的相關定理)

對於不完全為 0 的非負整數 a,b,gcd(a,b)表示 a,b 的最大公約數,必然存在無陣列整數對 x,y ,使得 gcd(a,b)=ax+by。
(因為當b==0時,y的值是可以任意取的)

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int x,y,d;
void extend_Ebuild(int a,int b)
{
    if(b==0){
        x=1;
        y=0;
        d=a;
        return;
    }
    else{
        extend_Ebuild(b,a%b);
        int temp=x;//此時的x,y裡面的值是上一步的資料(遞迴靠下面的資料),現在轉換成對應當前gcd(int a,int b)的x,y的值,
        x=y;
        y=temp-(a/b)*y;
    }
}
int main()
{
    int a,b;
    while(cin>>a>>b)
    {
        extend_Ebuild(a,b);
        printf("%d = %d * %d + %d * %d\n",d,a,x,b,y);
    }
    return 0;
}

上面已經列出找一個整數解的方法,在找到p * a+q * b = Gcd(a, b)的一組解p0,q0後,p * a+q * b = Gcd(a, b)的其他整數解滿足: p = p0 + b/Gcd(a, b) * t q = q0 - a/Gcd(a, b) * t(其中t為任意整數)

二.使用擴充套件歐幾里德演算法解決不定方程的辦法

對於不定整數方程pa+qb=c,若 c mod Gcd(a, b)=0,則該方程存在整數解,否則不存在整數解。即:(p/k)*a+(q/b)*b=c/k,如果c/k==gcd(a,b),則該方程存在整數解,否則不存在整數解。

至於pa+qb=c的整數解,只需將p * a+q * b = Gcd(a, b)的每個解乘上 c/Gcd(a, b) 即可,但是所得解並不是該方程的所有解,找其所有解的方法如下: 在找到p * a+q * b = Gcd(a, b)的一組解p0,q0後,可以 得到p * a+q * b = c的一組解p1 = p0*(c/Gcd(a,b)),q1 = q0*(c/Gcd(a,b)),p * a+q * b = c的其他整數解滿足: p = p1 + b/Gcd(a, b) * t q = q1 - a/Gcd(a, b) * t(其中t為任意
整數
) p 、q就是p * a+q * b = c的所有整數解。