前言
划水选手来把以前学的算法写博客上,防止以后忘了
然后先定义
g
c
d
(
a
,
0
)
=
a
gcd(a,0)=a
gcd(a,0)=a
欧几里得算法
求
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)即最大公约数,有什么用,能求
l
c
m
(
a
,
b
)
=
a
∗
b
/
g
c
d
(
a
,
b
)
lcm(a,b)=a*b/gcd(a,b)
lcm(a,b)=a∗b/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)递归即可
复杂度:
O
(
l
o
g
n
)
\mathcal O(logn)
O(logn)
扩展欧几里得
求
a
x
+
b
y
=
g
c
d
(
a
,
b
)
ax+by=gcd(a,b)
ax+by=gcd(a,b)的一组整数解
)当然保证一定有解
证明?因为我能求出来
方法:
我们发现,如果
b
=
0
b=0
b=0,那么显然答案显然是
{
x
=
1
y
=
0
\begin{cases}x=1\\y=0\end{cases}
{x=1y=0
既然是扩展欧几里得,那么我们就用欧几里得算法来
假设我们求出了
a
′
=
b
,
b
′
=
a
%
b
a'=b,b'=a\%b
a′=b,b′=a%b时的解
a
′
x
′
+
b
′
y
′
=
g
c
d
(
a
′
,
b
′
)
=
g
c
d
(
a
,
b
)
a'x'+b'y'=gcd(a',b')=gcd(a,b)
a′x′+b′y′=gcd(a′,b′)=gcd(a,b)
我们来化简一下
(
a
%
b
)
y
′
+
b
x
′
=
g
c
d
(
a
,
b
)
(a\%b)y'+bx'=gcd(a,b)
(a%b)y′+bx′=gcd(a,b)
我们发现现在离我们的目标
a
x
+
b
y
=
g
c
d
(
a
,
b
)
ax+by=gcd(a,b)
ax+by=gcd(a,b)还有一点距离,就是第一项
我们向目标靠近
a
y
′
+
b
x
′
=
g
c
d
(
a
,
b
)
+
(
a
−
a
%
b
)
y
′
a
y
′
+
b
x
′
=
g
c
d
(
a
,
b
)
+
⌊
a
b
⌋
b
y
′
a
y
′
+
b
(
x
′
−
⌊
a
b
⌋
y
′
)
=
g
c
d
(
a
,
b
)
\begin{aligned} ay'+bx'&=gcd(a,b)+(a-a\%b)y'\\ ay'+bx'&=gcd(a,b)+\left\lfloor\frac ab\right\rfloor by'\\ ay'+b(x'-\left\lfloor\frac ab\right\rfloor y')&=gcd(a,b) \end{aligned}
ay′+bx′ay′+bx′ay′+b(x′−⌊ba⌋y′)=gcd(a,b)+(a−a%b)y′=gcd(a,b)+⌊ba⌋by′=gcd(a,b)
这样我们只要递归就能找到解了
随便搞个代码
int EXgcd(const int a,const int b,int &x,int &y)
{
if(!b)
{
x=1,y=0;
return a;
}
const int res=EXgcd(b,a%b,y,x);
y-=a/b*x;
return res;
}
返回值是gcd(a,b),然后x,y定义一下变量直接传进去(都不用预赋值),函数做完里面就是求的x,y
然后的话,至于通解
我们发现
a
∗
b
/
g
c
d
(
a
,
b
)
=
b
∗
a
/
g
c
d
(
a
,
b
)
a*b/gcd(a,b)=b*a/gcd(a,b)
a∗b/gcd(a,b)=b∗a/gcd(a,b)
所以如果获取一组
{
x
′
y
′
\begin{cases}x'\\y'\end{cases}
{x′y′
那么通解就是
{
x
=
x
′
+
k
∗
b
/
g
c
d
(
a
,
b
)
y
=
y
′
+
k
∗
a
/
g
c
d
(
a
,
b
)
,
k
∈
Z
\begin{cases}x=x'+k*b/gcd(a,b)\\y=y'+k*a/gcd(a,b)\end{cases},k\in Z
{x=x′+k∗b/gcd(a,b)y=y′+k∗a/gcd(a,b),k∈Z
额外的应用
然后如果要求
a
x
+
b
y
=
c
ax+by=c
ax+by=c的整数解咋办咧?
若
c
%
g
c
d
(
a
,
b
)
≠
0
c\%gcd(a,b)\neq0
c%gcd(a,b)=0无解
显然在x,y都是整数的时候
a
x
+
b
y
ax+by
ax+by一定是
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)的整数倍
所以相当于变成求
a
x
+
b
y
=
l
∗
g
c
d
(
a
,
b
)
ax+by=l*gcd(a,b)
ax+by=l∗gcd(a,b)的整数解
假设我们求出了
a
x
+
b
y
=
g
c
d
(
a
,
b
)
ax+by=gcd(a,b)
ax+by=gcd(a,b)的解,貌似x、y各乘
l
l
l就好了,通解也是原本的通解分别乘
l
l
l
结语
这篇博客巨水,感兴趣的可以去看看裴蜀定理,那个看起来更牛逼bushi一点