1. 程式人生 > >擴充套件歐幾里得演算法(乘法逆元 最小正整數解 直線上的整數點)

擴充套件歐幾里得演算法(乘法逆元 最小正整數解 直線上的整數點)

參考資料:

本文證明過程來自百度百科和劉汝佳的演算法入門經典

擴充套件歐幾里得演算法介紹:

前置知識:歐幾里得演算法(其實就是輾轉相除法,用於計算兩個整數a,b的最大公約數。)

歐幾里得演算法:

在開始之前,我們先說明幾個定理:

gcd(a,b)=gcd(b,a)=gcd(-a,b)=gcd(|a|,|b|)

公式表述及證明

gcd(a,b)=gcd(b,a mod b)

證明:a可以表示成a = kb + r,則r = a mod b

假設d是a,b的一個公約數,則有

d|a, d|b,而r = a - kb,因此d|r

因此d是(b,a mod b)的公約數

假設d 是(b,a mod b)的公約數,則

d | b , d |r ,但是a = kb +r

因此d也是(a,b)的公約數

因此(a,b)和(b,a mod b)的公約數是一樣的,其最大公約數也必然相等,得證

程式碼:

根據上述公式,我們可以用遞迴來實現GCD函式(邊界條件就是a,b的最大公約數是b本身的時候,也就是a%b==0的時候),程式碼如下:

int gcd(int a,int b)
{
    return b?gcd(b,a%b):a;
}

擴充套件歐幾里得演算法:

擴充套件歐幾里德演算法是歐幾里得演算法的擴充套件,是用來在已知a, b的情況下求解一組x,y,使它們滿足貝祖等式: ax+by = gcd(a, b) =d(解一定存在,根據數論中的相關定理)。擴充套件歐幾里德常用在求解模線性方程及方程組中。

注意:很容易忽略的一個地方:對於不全為0非負整數a,b(擴充套件歐幾里得演算法要求傳入的引數a,b是非負的),gcd(a, b)表示a, b的最大公約數,必定存在整數對x,y,滿足a*x+b*y==gcd(a, b)。如果有引數含有負數,則需要特殊處理,處理方式如下:(來自維基百科)

求解 x,y的方法及證明 (設 a>b)

1,顯然當 b=0,gcd(a,b)=a。此時 x=1,y=0;

2,a>b>0 時,設 ax1+ by1= gcd(a,b);

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

根據樸素的歐幾里德原理有 gcd(a,b) = gcd(b,a mod b);

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

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

說明: a-[a/b]*b即為mod運算。[a/b]代表取小於a/b的最大整數。

也就是ax1+ by1 == ay2+ b(x2- [a / b] *y2);

根據恆等定理得:x1=y2; y1=x2- [a / b] *y2;

這樣我們就得到了求解 x1,y1 的方法:x1,y1 的值基於 x2,y2.

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

遞迴邊界:gcd(a,0)=1*a-0*0=a。

程式碼實現一:

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

程式碼實現二(推薦):

int exGcd(int a,int b,int &d,int &x,int &y)
{
    if(!b) { d=a;x=1;y=0; }
    else { gcd(b,a%b,d,y,x); y-= x*(a/b); }
}

擴充套件歐幾里得演算法的應用:

應用一:求解乘法逆元(A和MOD互素的時候才存在,否則不存在逆元)

首先同餘模定理如下:

(a+b)%c=(a%c+b%c)%c;

(a*b)%c=(a%c*b%c)%c;

也就是說對於取模的加減法,和乘法我們都可以運用同餘模定理來進行計算,那麼,對於除法我們應該怎麼辦呢?首先想到的就是把除法轉換成乘法,然後就可以運用定理了。怎麼轉換呢,在普通乘法中,我們知道,除以一個數就等於乘上一個數的倒數,其實這個倒數就是我們所謂的逆元。A*(A的逆元)=單位元。在普通的乘法中 A的逆元就是它的倒數。 那麼,在模n乘法中,我們應該怎麼求逆元呢?我們設A的逆元為X,那麼我們就可以得到(A*X)%MOD=1(模n乘法的單位元也是1)。對這個式子進行變形 ,就可以得到:

(A*X)%MOD=1;那麼肯定存在k使得

A*X=k*MOD+1;

移項可得:A*X-k*MOD=1;

所以,當A和MOD互素時,就可以寫成

A*X-k*MOD=gcd(A,MOD);

如果把A看做a,MOD看做b,X看做x,-k看做y的話,則上式可化為:

ax+by=gcd(a,b);

這樣就可以用擴充套件歐幾里得演算法求出來x了,也就是我們要找的逆元。

應用二:求解ax=c(mod b)(也就是ax+by=c(同上逆元的變化方式))的x的最小整數解

ax=c(mod b)可以轉化為ax+by=c。(變化的方式同求逆元的時候的變化。)

我們可以用擴充套件歐幾里得演算法得出ax+by=gcd(a,b) 的一組解(x1,y1),那麼其他解呢?任取另一組解(x2,y2),則ax1+by1=ax2+by2(因為它們都等於gcd(a,b) ),變形得a(x1-x2)=b(y2-y1)。假設gcd(a,b)=g,方程左右兩邊同時除以g(如果g=0,說明a或b等於0,可以特殊判斷),得a'(x1-x2)=b'(y2-y1),其中a'=a/g,b'=b/g。注意,此時a'和b'互素(想想分數的化簡),則因此x1-x2一定是b'的整數倍(因為a'中不包含b',所以x1-x2一定包含b')。設它為kb',計算得y2-y1=ka'。注意,上述的推導過程並沒有用到“ax+by的右邊是什麼”,因此得出以下結論:

設a,b,c為任意整數,若方程ax+by=c的一組解是(x0,y0),則它的任意整數解都可以寫成(x0+kb',y0-ka'),其中a'=a/gcd(a,b),b'=b/gcd(a,b),k取任意整數。

這樣我們就可以求出來最小的整數解了。(先用擴充套件歐幾里得演算法求出一組解,然後進行變換)。

具體實現方式看程式碼的註釋

int cal(int a,int b,int c)
{
	int x,y;
	int gcd=(a,b,x,y);
	if(c%gcd!=0)
		return -1;//代表無解 
	//  ax0+by0=gcd(a,b)                                方程一 
	//同時乘以c/gcd(a,b)得   
	// (a*c/gcd(a,b))*x0+(b*c/gcd(a,b))*y0=c;
	// 令 x1=c/gcd(a,b)*x0  y1=c/gcd(a,b)*y0;
	// 則可得 ax1+by1=c                                 方程二 
	// 這時得出方程的一個解   x1=x0*c/gcd(a,b)     y1=y0*c/gcd(a,b)  
	x*=c/gcd; //將 方程一的一個特解轉化成方程2的一個特解 
	//套用上文的公式可得對方程二
	// b'=b/gcd(a,b);
	b/=gcd;   
	if(b<0)//處理小於0的特殊情況 
		b=-b;
	//對特解x  +- kb'  找到最小整數解
	//設x=kb'+r
	//那麼我們想要求的整數解就是r
	//直接取模運算即可 
	int ans=x%b; 
	//把負數的r轉化成正數的 
	if(ans<=0)
		ans+=b;
	return ans;
}

應用三:直線上的整數點

在平面座標系下,ax+by=c是一條直線方程。知道一個點,我們就可以用應用二中的方法去求直線上的所有整數點

END~

相關推薦

擴充套件演算法乘法 整數 直線數點

參考資料: 本文證明過程來自百度百科和劉汝佳的演算法入門經典。 擴充套件歐幾里得演算法介紹: 前置知識:歐幾里得演算法(其實就是輾轉相除法,用於計算兩個整數a,b的最大公約數。) 歐幾里得演算法: 在開始之前,我們先說明幾個定理: gcd(a,b)=gcd(b,a

擴充套件演算法乘法C語言版

#include <stdio.h>   int ExtendedEuclid( int f,int d ,int *result);   int main()   {   int x,y,z;   z = 0;   printf("輸入

擴充套件演算法及求

師父的擴充套件歐幾里得演算法詳細部落格師父喲 大神的求逆元詳細部落格大神的呢 gcd(a,b)即求a和b的最大公約。用輾轉相除法求得。 擴充套件歐幾里得演算法是歐幾里得演算法(又叫輾轉相除法)的擴充套件。除了計算a、b兩個整數的最大公約數,此演算法還能找到

演算法擴充套件演算法乘法

最近看了一本書《程式設計師》裡面說的一個面試題: 求兩個數的最大公約數: SoEasy的題目看過C 的人都知道怎麼寫這個程式 1.傳統方法:窮舉 #include <math.h>int main(){int m=1970,n=1066,p=0;p=m<n?m:n;for(;p>=1

擴充套件演算法乘法

eg:求5關於模14的乘法逆元 15 = 5*2+1 5 = 4*1+1 說明5與14互素,存在5關於14的乘法逆元 1 = 5-4 = 5-(14-5*2)= 5*3-14 因此5關於模14的乘法逆元為3  a存在模b的乘法逆元的充要條件是gcd(a,b)= 1 互質

演算法複習——擴充套件演算法擴充套件,整除

①歐幾里得演算法 就是求gcd的有趣的輾轉相除法,不再贅述啦0v0 程式碼: int gcd(int a,int b) { if(b==0) return a; else return gcd(b,a%b); } ②擴充套件歐幾里得演算法 需要解決這樣的問題:兩個非0整數a,b

擴充套件演算法exgcd 學習筆記

定義 首先引入一個叫做貝祖定理的東西 對於∀a,b∈N,總是∃x,y∈Z,使ax+by=(a,b) 已知a,b,求ax+by=(a,b)一組可行解的演算法即為擴充套件歐幾里得演算法。 演

擴充套件演算法乘法

計算乘法逆元,比如3mod8的乘法逆元為3 是如何用歐幾里得演算法計算的呢??? 數對 x,y ,使得 gcd(a,b)=ax+by。 c++語言實現: #include <iostream&

演算法大公因子擴充套件乘法

一、歐幾里得演算法歐幾里得演算法又稱輾轉相除法,是指用於計算兩個正整數a,b的最大公約數。gcd(a,b)=gcd(b,a mod b)。演算法描述:1. 輸入:兩個非負整數a,b,且a≥b。2. 輸出

51nod 1256 乘法擴充套件演算法

思路1:把k*M%N=1可以寫成一個不定方程,(k*M)%N=(N*x+1)%N,那麼就是求k*M-N*x=1使得k最小,不定方程利用擴充套件歐幾里得演算法 --------------------------------------------------------

POJ-1061-青蛙的約會 擴充套件演算法

原題連結: http://poj.org/problem?id=1061 兩隻青蛙在網上相識了,它們聊得很開心,於是覺得很有必要見一面。它們很高興地發現它們住在同一條緯度線上,於是它們約定各自朝西跳,直到碰面為止。可是它們出發之前忘記了一件很重要的事情,既沒有問清楚對方的特徵,也沒有約定

HDU-2669-Romantic 擴充套件演算法

原題連結: http://acm.hdu.edu.cn/showproblem.php?pid=2669 The Sky is Sprite. The Birds is Fly in the Sky. The Wind is Wonderful. Blew Throw the Trees

POJ-2142-The Balance 擴充套件演算法

原題連結: Ms. Iyo Kiffa-Australis has a balance and only two kinds of weights to measure a dose of medicine. For example, to measure 200mg of aspiri

演算法學習——演算法&擴充套件演算法

最大公約數/歐幾里德演算法(gcd) 歐幾里德演算法又稱輾轉相除法,證明可以度娘。 個人簡單腦部就是a和b兩個數的模還是a和b的最大公約數 int型別  int gcd(int a, int b) {return a%b==0?b:gcd(b,a%b);} long l

各種密碼學演算法的GUI程式設計實現DES、AES、Present、擴充套件演算法、素性檢測

encryption-algorithm 各種密碼學演算法的 C# GUI程式設計實現,包含: DES AES Present 擴充套件歐幾里得演算法 素性檢測 最終的結果 DES加密 DES解密

乘法擴充套件演算法、二元一次方程、a的n次方取餘

知識點:乘法逆元,逆元的求法,二元一次方程求通解,a的n次方求餘數 一,乘法逆元 乘法逆元的概念類似於倒數(ax=1,a−1=x),不過是在取餘數的情況下的倒數。 如果(a×x)%p=1,則稱x是a模p的逆元。另一種記法:ax=1(modp),即等

的個數直線的點數論-擴充套件演算法

Description  已知x,y滿足如下條件:  ax+by+c=0 ; x1 <= x <= x2 ; y1 <= y <= y2 ; x,y均為整數。  其中:a,b,c,x1,x2,y1,y2 都是絕對值不超過 10^8 的整數。  求(x,

乘法【費馬定理+擴充套件演算法

乘法逆元 何為乘法逆元? 對於兩個數a,pa,p若gcd(a,p)=1gcd(a,p)=1則一定存在另一個數bb,使得ab≡1(modp)ab≡1(modp),並稱此時的bb為aa關於11模pp的乘法逆元。我們記此時的bb為inv(a)inv(a)或a−1a

POJ 2115 for求迴圈次數-數論-同餘方程+擴充套件演算法

題意:給定for迴圈的初始值,結束值和增量,還有一個模,求最少的迴圈次數。 分析: 讀完題後應該就知道是一個同餘的概念,所以就是解一個一元一次同餘方程,像上題一樣用擴充套件歐幾里得演算法。這題的trick點是k最大為32,那麼2^32超出了int,要用long long,所

青蛙的約會擴充套件演算法+不定方程求解

1.折磨了我好久,不過大概是懂了。 2.題目: 兩隻青蛙在網上相識了,它們聊得很開心,於是覺得很有必要見一面。它們很高興地發現它們住在同一條緯度線上,於是它們約定各自朝西跳,直到碰面