(1)欧几里得算法
defination:if x and y are positive and x >= y,then gcd(x,y) = gcd(x mod y,y)。又叫辗转相除法,用于求解最大公约数,时间复杂度为O(log n)(n 为二进制的长度)。
proof::首先,我们应该知道:如果一个数可以除尽x,y,那么它一定能除尽x-y。那么我们可以得到gcd(x,y) = gcd (x-y,y).以此类推,
gcd(x-y,y) = gcd(x-2y,y) =...........=gcd(x mod y,y)。
又叫辗转相除法,用于求解最大公约数,时间复杂度为O(n^3)(n 为二进制的长度)。
递归:
#include <iostream>
using namespace std;
int Euclid(int x,int y)
{
if(y == 0)
return x;
else
return Euclid(y,x % y);
}
int main()
{
int x,y;
cin >> x >> y;
if(x < y)
swap(x,y);
cout << Euclid(x,y) << endl;
system("pause");
return 0;
}
Lemma 1. if a >= b ,then a mod b < a / 2
proof:(1) 如果b >= a / 2,那么 a mod b 一定小于 a / 2
(2) 如果 b < a / 2, 那么 a mod b <= b < a / 2
(2)扩展的欧几里得算法
defination: If d divides both a and b, and d = ax + by for some interger x and y, then necessarily d = gcd(a,b)。
proof:如果d是a,b的公约数则d <= gcd(a,b)。又因为d = ax + by,则gcd(a,b)必然整除d,即d >= gcd(a,b)。所以 d = gcd(a,b)。
主要应用:
(1) 解不定方程
//a >= b
gcd(a,b) = gcd (b,a mod b) = bx1 + (a mod b)y1 = bx1 + (a - (a/b) * b) * y1 = ay1 + b(x1 - a/b*y1)
所以 x = y1,y =(x1 - a/b*y1)
递归:
(1) if(b == 0),gcd(a,b) = a,x = 1, y = 0(y可任意取,不同的y对应不同的解)
(2) if(b != 0) x = y1,y =(x1 - a/b*y1)
int extended_euclidean(int a, int b, int &x, int &y)
{
if (b == 0)
{
x = 1; y = 0; return b;
}
int g = extended_euclidean(b, a % b, x, y);
int t = x - a / b * y;
x = y;
y = t;
return g;
}
此时也可得到一系列解:
x = x0 + b*k;
y = y0 - a*k
关于这个算法的时间复杂度,可以看出这个算法和欧几里得算法不同之处在于每次都求出了x,y的一组解,但是实质还是在做欧几里得算法。所以时间复杂度为O(n^3)
(2)求乘法逆原(multiplicative inverse)
defination:x is the multiplicative inverse of a modulo N if ax ≡ 1 (mod N)
Modular division theorem:For any a mod N, a has a multiolicative inverse modulo N if and only if it is relativetly prime to N .When this inverse exist , it can be found in time O(n^3)
int extended_euclidean(int a, int b, int &x, int &y)
{
if (b == 0)
{
x = 1; y = 0; return b;
}
int g = extended_euclidean(b, a % b, x, y);
int t = x - a / b * y;
x = y;
y = t;
return g;
}
其中x为a mod b 的逆元,y为 b mod a 的逆元