擴充歐幾裡德演算法,裡德演算法
本來數學就不好,看到LRJ的數學專題直接跪了,上網百度了一下才知道擴充歐幾裡德演算法的證明過程。
首先說一下樸素歐幾裡德演算法,就是輾轉相除法,很簡單。
int gcd(int a,int b){ return b == 0 ? a : gcd(b,a % b);}
下面主要說一下擴充歐幾裡得演算法。
給出a,b 求 x,y使得 a * x + b * y = gcd(a,b);
我們不妨設a > b,且 x > y
那麼當b = 0 的時候 gcd(a,b) = a,因此 x = 1 , y = 0;
如果b != 0 的時候,我們知道
ax1 + by1 = gcd(a,b) = bx2 + (a % b)y2;(根據樸素歐幾裡德)
我們化簡一下這個式子
ax1 + by1 = bx2 + (a - (a / b) * b)y2;
ax1 + by1 = bx2 + a * y2 - (a / b) * b * y2;
ax1 + by1 = a * y2 + b * (x2 - (a/b) * y2);
因此 x1 = y2;
y1 = (x2 - (a/b) * y2);
也就是說每一層的x,y可以由上一層的x,y求出,遞迴終點為 b = 0;
#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<vector>#include<stack>#include<queue>#include<map>#include<set>#include<list>#include<string>#include<cmath>#include<sstream>#include<ctime>using namespace std;#define _PI acos(-1.0)#define INF 1 << 10#define esp 1e-6typedef long long LL;typedef unsigned long long ULL;typedef pair<int,int> pill;/*======================================================================================*/void gcd(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); }}int main(){ int x,y,a,b,c; while(scanf("%d%d",&a,&b) != EOF){ x = max(a,b); y = x; if(a < b) /*保證a > b */ swap(a,b); gcd(a,b,c,x,y); /*代表a * x + b * y = c */ printf("(%d * %d) + (%d * %d) = %d\n",a,x,b,y,c); } return 0;}
ps:另外,要求多組解的話,假設已經求了一組解為(x0,y0),設:a' = a / gcd(a,b), b' = b / gcd(a,b),那麼其餘任意解都可以寫成(x0 + k * b' ,y0 - k * a');
擴充歐幾裡得演算法 好懂一點
歐幾裡德演算法又稱輾轉相除法,用於計算兩個整數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)的公約數是一樣的,其最大公約數也必然相等,得證
歐幾裡德演算法就是根據這個原理來做的,其演算法用C++語言描述為:
int
Gcd(int a, int b)
{
if(b ==
0)
return a;
return
Gcd(b, a % b);
}
當然你也可以寫成迭代形式:
int
Gcd(int a, int b)
{
while(b !=
0)
{
int r = b;
b = a % b;
a =
r;
}
return
a;
}
本質上都是用的上面那個原理。
補充:
擴充歐幾裡德演算法是用來在已知a,
b求解一組x,y使得a*x+b*y=Gcd(a,b)(解一定存在,根據數論中的相關定理)。擴充歐幾裡德常用在求解模線性方程及方程組中。下面是一個使
用C++的實現:
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;
}
把這個實現和Gcd的遞迴實現相比,發現多了下面的x,y賦值過程,這就是擴充歐幾裡德演算法的精髓。
可以這樣思考:
對於a' = b,
b' = a % b 而言,我們求得 x, y使得 a'x + b'y = Gcd(a', b')
由於b' = a
% b = a - a / b * b (註:這裡的/是程式設計語言中的除法)
那麼可以得到:
a'x + b'y
= Gcd(a', b') ===>
bx + (a - a / b * b)y = Gcd(a', b') = Gcd(a, b)
===>
ay +b(x - a / b*y) = Gcd(a, b)
因此對於a和b而言,他們的相對應的p,q分別是
y和(x-a/b*y).
在網上看了很多關於不定方程方程求解的問題,可都沒有說全,都只說了一部分,看了好多之後才真正弄清楚不定方程的求解全過程,步驟如下:
求a * x
+ b * y = n的整數解。
1、先計算Gcd(a,b),若n不能被Gcd(a,b)整除,則方程無整數解;否則,在方程兩邊同時除以Gcd(a,b),得到新的不定方程a'
* x + b' * y = n',此時Gcd(a',b')=1;
2、利用上面所說的歐幾裡德演算法求出方程a' * x + b' * y = 1的一組整數解x0,y0,則n' * x0,n' *
y0是方程a' * x + b' * y = n'的一組整數解......餘下全文>>
擴充歐幾裡得演算法 好懂一點
歐幾裡德演算法又稱輾轉相除法,用於計算兩個整數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)的公約數是一樣的,其最大公約數也必然相等,得證
歐幾裡德演算法就是根據這個原理來做的,其演算法用C++語言描述為:
int
Gcd(int a, int b)
{
if(b ==
0)
return a;
return
Gcd(b, a % b);
}
當然你也可以寫成迭代形式:
int
Gcd(int a, int b)
{
while(b !=
0)
{
int r = b;
b = a % b;
a =
r;
}
return
a;
}
本質上都是用的上面那個原理。
補充:
擴充歐幾裡德演算法是用來在已知a,
b求解一組x,y使得a*x+b*y=Gcd(a,b)(解一定存在,根據數論中的相關定理)。擴充歐幾裡德常用在求解模線性方程及方程組中。下面是一個使
用C++的實現:
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;
}
把這個實現和Gcd的遞迴實現相比,發現多了下面的x,y賦值過程,這就是擴充歐幾裡德演算法的精髓。
可以這樣思考:
對於a' = b,
b' = a % b 而言,我們求得 x, y使得 a'x + b'y = Gcd(a', b')
由於b' = a
% b = a - a / b * b (註:這裡的/是程式設計語言中的除法)
那麼可以得到:
a'x + b'y
= Gcd(a', b') ===>
bx + (a - a / b * b)y = Gcd(a', b') = Gcd(a, b)
===>
ay +b(x - a / b*y) = Gcd(a, b)
因此對於a和b而言,他們的相對應的p,q分別是
y和(x-a/b*y).
在網上看了很多關於不定方程方程求解的問題,可都沒有說全,都只說了一部分,看了好多之後才真正弄清楚不定方程的求解全過程,步驟如下:
求a * x
+ b * y = n的整數解。
1、先計算Gcd(a,b),若n不能被Gcd(a,b)整除,則方程無整數解;否則,在方程兩邊同時除以Gcd(a,b),得到新的不定方程a'
* x + b' * y = n',此時Gcd(a',b')=1;
2、利用上面所說的歐幾裡德演算法求出方程a' * x + b' * y = 1的一組整數解x0,y0,則n' * x0,n' *
y0是方程a' * x + b' * y = n'的一組整數解......餘下全文>>