欧几里得算法(辗转相除法)的原理(点击这里)就可以解决。
代码实现思路 :
对于任意的正整数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
∴ c∣a,c∣b
(
c
∣
a
=
a
c|a = a
c∣a=a可以整除以
c
c
c)
∵
r
=
a
−
k
b
\because r = a - kb
∵r=a−kb
∴
c
∣
r
\therefore c | r
∴c∣r
∴
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,b∈N
证明:
当
b
=
0
b = 0
b=0 时,等式为
a
x
+
0
∗
y
=
g
c
d
(
a
,
0
)
ax + 0 * y = gcd (a, 0)
ax+0∗y=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=a−a/b∗b
∴
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+(a−a/b∗b)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/b∗b)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(x2−a/b∗y2)
∴
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=x2−a/b∗y2
接下来的步骤直接递归就好了
代码实现:
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;
}