欧几里得算法及其拓展欧几里得算法

欧几里得算法(辗转相除法)的原理(点击这里)就可以解决。

代码实现思路 :

对于任意的正整数a, b, 都有
a = k b + r   ( k ,   r ∈   N ) a = kb + r\ (k,\ r \in\ N) a=kb+r (k, r N)
r = a   %    b r = a\ \%\ \ b r=a %  b

假设 c 为a, b的最大公约数

c = g c d ( a , b ) c = gcd(a, b) c=gcd(a,b)
∴   c ∣ a , c ∣ b \therefore \ c|a, c | b  ca,cb
( c ∣ a = a c|a = a ca=a可以整除以 c c c)
∵ r = a − k b \because r = a - kb r=akb
∴ c ∣ r \therefore c | r cr
∴ c = g c d ( b , r ) \therefore c = gcd(b, r) c=gcd(b,r)

结论: g c d ( a , b ) = g c d ( b , a   %   b ) gcd(a, b) = gcd(b, a\ \%\ b ) gcd(a,b)=gcd(b,a % b)

最大公约数(欧几里得算法)

递归版本:

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

非递归(迭代)版本:

int gcd(int a, int b) {
    while (b) {
        a = a % b;
        swap(a, b);
    }
    return a;
}

顺便安利一波求最小公倍数的代码

最小公倍数

int lcm(int a, int b) {
    return a / gcd(a, b) * b;  //先除后乘可以防止溢出
}

拓展欧几里得算法

简单来讲,就是求解贝祖等式的解(注意求解出来的x,y不是最小的整数解)形如

a x + b y = g c d ( a , b ) ax + by = gcd(a, b) ax+by=gcd(a,b)
a , b ∈ N a, b \in N a,bN

证明:

b = 0 b = 0 b=0 时,等式为 a x + 0 ∗ y = g c d ( a , 0 ) ax + 0 * y = gcd (a, 0) ax+0y=gcd(a,0)
∴ a x = a \therefore ax = a ax=a
∴ x = 1 \therefore x = 1 x=1
此时 y y y 我们令它为 0 0 0

也就是 x = 1, y = 0

a x 1 + b y 1 = g c d ( a , b ) ax_1 + by_1 = gcd(a, b) ax1+by1=gcd(a,b)
b x 2 + ( a   %   b ) y 2 = g c d ( a , b ) bx_2 + (a\ \%\ b) y_2 = gcd(a, b) bx2+(a % b)y2=gcd(a,b)
根据欧拉几得算法又得出 : g c d ( a , b ) = g c d ( b , a   %   b ) gcd (a, b) = gcd (b, a\ \%\ b) gcd(a,b)=gcd(b,a % b)
∴ a x 1 + b y 1 = b x 2 + ( a   %   b ) y 2 \therefore ax_1 + by_1 = bx_2 + (a\ \%\ b) y_2 ax1+by1=bx2+(a % b)y2
∵ a   %   b = a − a / b ∗ b \because a\ \%\ b = a - a / b * b a % b=aa/bb
∴ a x 1 + b y 1 = b x 2 + ( a − a / b ∗ b ) y 2 \therefore ax_1 + by_1 = bx_2 + (a - a / b * b) y_2 ax1+by1=bx2+(aa/bb)y2
∴ a x 1 + b y 1 = b x 2 + a y 2 − ( a / b ∗ b ) y 2 \therefore ax_1 + by_1 = bx_2 + ay_2 - (a / b * b ) y_2 ax1+by1=bx2+ay2(a/bb)y2
∴ a x 1 + b y 1 = a y 2 + b ( x 2 − a / b ∗ y 2 ) \therefore ax_1 + by_1 = ay_2 + b(x_2 - a / b * y_2) ax1+by1=ay2+b(x2a/by2)

∴ x 1 = y 2 \therefore x_1 = y_2 x1=y2
∴ y 1 = x 2 − a / b ∗ y 2 \therefore y_1 = x_2 - a / b * y_2 y1=x2a/by2
接下来的步骤直接递归就好了
代码实现:

int exgcd(int a, int b, int &x, int &y) {
	if (!b) {
		x = 1;
		y = 0;
		return a;
	}
	int tx, ty;
	int res = exgcd(b, a % b, tx, ty);
	x = ty;
	y = tx - a / b * ty;
	return res;
}

简化版

int exgcd(int a, int b, int &x, int &y) {
	if (!b) {
		x = 1;
		y = 0;
		return a;
	}
	int res = exgcd(b, a % b, y, x);
	y -= a / b * x;
	return res;
}

你可能感兴趣的:(~数学)