欧几里得算法
简介
欧几里得算法,也叫辗转相除,简称
g
c
d
gcd
gcd,用于计算两个整数的最大公约数.
定义
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b) 为整数
a
a
a 与
b
b
b 的最大公约数.
引理: g c d ( a , b ) = g c d ( b , a m o d    b ) gcd(a,b)=gcd(b,a\mod b) gcd(a,b)=gcd(b,amodb)
1.设
a
a
a 与
b
b
b 的最大公约数为
g
g
g,则
a
=
m
1
×
g
a=m_1\times g
a=m1×g ,
b
=
m
2
×
g
b=m_2\times g
b=m2×g 易知
m
1
m_1
m1 与
m
2
m_2
m2 互质。
2.设
q
=
⌊
a
b
⌋
q=\lfloor\dfrac{a}{b}\rfloor
q=⌊ba⌋ ,
r
=
a
m
o
d
  
b
=
a
−
p
×
b
=
(
m
1
−
p
×
m
2
)
×
g
r=a\mod b=a-p\times b=(m_1-p\times m_2)\times g
r=amodb=a−p×b=(m1−p×m2)×g,由1得
b
b
b 与
r
r
r 的最大公约数为
g
g
g ,且
m
2
m_2
m2 与
(
m
1
−
p
×
m
2
)
(m_1-p\times m_2)
(m1−p×m2) 互质。
证明
m
2
m_2
m2 与
(
m
1
−
p
×
m
2
)
(m_1-p\times m_2)
(m1−p×m2) 互质:
假设 m 2 m_2 m2 与 ( m 1 − p × m 2 ) (m_1-p\times m_2) (m1−p×m2) 的最大公约数为 k k k,且 k ≥ 2 k \ge 2 k≥2(两数不互质)。
   ⟹    m 2 = n 1 × k \implies m_2=n_1\times k ⟹m2=n1×k, m 1 − p × m 2 = n 2 × k m_1-p\times m_2=n_2\times k m1−p×m2=n2×k
a − p × b = r    ⟺    a = p × b + r    ⟺    a-p\times b=r\iff a=p\times b + r\iff a−p×b=r⟺a=p×b+r⟺
a = n 2 × k × g + p × n 1 × k × g    ⟺    a = n_2\times k\times g + p\times n_1\times k\times g\iff a=n2×k×g+p×n1×k×g⟺
a = ( n 2 + p × n 1 ) × k g a=(n_2+p\times n_1)\times kg a=(n2+p×n1)×kg,又 b = n 1 × k g b=n_1\times k g b=n1×kg
则 a a a 与 b b b 的最大公约数为 k g kg kg ,跟已知矛盾,即 m 2 m_2 m2 与 ( m 1 − p × m 2 ) (m_1-p\times m_2) (m1−p×m2) 互质.
当 b = 0 b=0 b=0 时 g c d ( a , b ) = a gcd(a, b)=a gcd(a,b)=a
int gcd(int a. int b) //a,b大小不影响
{
return b ? gcd(b. a%b) : a;
}
扩展欧几里得算法
简介
扩展欧几里德算法,简称
e
x
g
c
d
exgcd
exgcd 是用来在已知a, b求解一组x,y,使它们满足贝祖等式/裴蜀定理(不了解可以戳一下(σ゚∀゚)σ…:*☆):
a
x
+
b
y
=
g
c
d
(
a
,
b
)
=
d
ax+by = gcd(a, b) =d
ax+by=gcd(a,b)=d
让我们简单的推导一下过程
a
x
+
b
y
=
g
c
d
(
a
,
b
)
=
g
c
d
(
b
,
a
%
b
)
=
b
x
′
+
(
a
%
b
)
y
′
ax+by=gcd(a,b)=gcd(b,a\%b)=bx'+(a\%b)y'
ax+by=gcd(a,b)=gcd(b,a%b)=bx′+(a%b)y′
然后我们就可以开始了
   ⟹    a x + b y = b x ′ + a y ′ − ( a / b ) b y ′ = a y ′ + b ( x ′ − ( a / b ) y ′ ) \implies ax+by=bx'+ay'-(a/b)by'=ay'+b(x'-(a/b)y') ⟹ax+by=bx′+ay′−(a/b)by′=ay′+b(x′−(a/b)y′)
于是得到一组解
x
=
y
′
,
y
=
x
′
−
(
a
/
b
)
y
′
x=y',y=x'-(a/b)y'
x=y′,y=x′−(a/b)y′
接着考虑边界条件
(
b
=
0
)
(b=0)
(b=0),
a
x
=
g
c
d
(
a
,
0
)
ax=gcd(a, 0)
ax=gcd(a,0) 显然成立.
当然,不定方程会有很多很多解,这时,我们设最小正整数解为
x
0
,
y
0
x_0, y_0
x0,y0,则通解为
x
=
x
0
+
b
g
c
d
(
a
,
b
)
,
y
=
y
0
+
a
g
c
d
(
a
,
b
)
x=x_0+\dfrac{b}{gcd(a, b)}, y=y_0+\dfrac{a}{gcd(a, b)}
x=x0+gcd(a,b)b,y=y0+gcd(a,b)a
至于证明,它死了,将通解带入方程式即可.
应用
hdu2669(模板题)
题目描述
给定两个数
a
,
b
a, b
a,b ,求满足
a
x
+
b
y
=
1
ax+by=1
ax+by=1 的
x
,
y
x,y
x,y 且
x
x
x 为满足条件的最小正整数.
题解
用扩展欧几里得,迭代求出最小的
x
x
x 即可.
代码
#include <bits/stdc++.h>
#define LL long long
using namespace std;
void exgcd(LL a, LL b, LL &x, LL &y)
{
if (!b)
{
x = 1, y = 0;
return ;
}
exgcd(b, a%b, y, x);
y -= x * (a/b);
}
LL gcd(LL a, LL b)
{
return b ? gcd(b, a%b) : a;
}
int main()
{
LL a, b, x, y;
while (scanf("%lld%lld", &a, &b) == 2)
{
if (gcd(a, b) != 1)
{
puts("sorry");
continue;
}
exgcd(a, b, x, y);
while (x < 0)
{
x += b;
y -= a;
}
// x = (x % b + b) % b;
printf("%lld %lld\n", x, y);
}
return 0;
}
洛谷P1082(同余方程)
题目描述
求关于
x
x
x 的同余方程
a
x
≡
1
(
m
o
d
b
)
a x \equiv 1 \pmod {b}
ax≡1(modb) 的最小正整数解。
题解
a
x
≡
1
(
m
o
d
b
)
  
⟹
  
a
x
+
b
y
=
1
a x \equiv 1 \pmod {b}\implies ax+by=1
ax≡1(modb)⟹ax+by=1
代码
#include <bits/stdc++.h>
#define LL long long
using namespace std;
void exgcd(LL a, LL b, LL &x, LL &y)
{
if (!b)
{
x = 1, y = 0;
return ;
}
exgcd(b, a%b, y, x);
y -= x * (a/b);
}
int main()
{
LL a, b, x, y;
scanf("%lld%lld", &a, &b);
exgcd(a, b, x, y);
while (x < 0)
x += b;
printf("%lld\n", x);
return 0;
}