学习扩展欧几里得算法,我们得先知道欧几里得算法,可以看这里,简单来说就是在 O ( l o g n ) O(log\ n) O(log n)的时间内,求出 g c d ( a , b ) gcd(a,b) gcd(a,b)。
而扩展欧几里得算法相当于是欧几里得算法的逆过程,
扩展欧几里得算法求得是整数
x
,
y
x,y
x,y,使得
a
x
+
b
y
=
g
c
d
(
a
,
b
)
ax+by=gcd(a,b)
ax+by=gcd(a,b)。
当然
x
,
y
x,y
x,y会有多组。
具体的求法是在欧几里得的求法中回溯。
模板题:
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int n;
int exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1,y=0;
return a;
}
int d=exgcd(b,a%b,y,x);//a,b交换位置,x,y的位置也改变
y-=a/b*x;
return d;
}
int main()
{
scanf("%d",&n);
while(n--)
{
int a,b,x,y;
scanf("%d%d",&a,&b);
int k=exgcd(a,b,x,y);
printf("%d %d\n",x,y);
}
return 0;
}
扩展欧几里得求解ax+by=m的式子(m%gcd(a,b)==0)
这个式子有解的前提:
m
%
g
c
d
(
a
,
b
)
=
=
0
m\%gcd(a,b)==0
m%gcd(a,b)==0 ;
然后就是这个方程如果没有对x和y有范围上的要求的话是有无线的解的
我们通过上面的模板可以求解出 ax+by=gcd(a,b)的一个特解 x y 然后等式俩边同时乘以m/gcd(a,b) 那么是不是就变成了ax+by=m的式子 ,此时的x和y也是乘过m/gcd(a,b)的,即此时x y是ax+by=m 的一个特解
现在的问题是怎么求其他的解:
我们让式子
a
x
+
b
y
=
m
ax+by=m
ax+by=m中
x
+
b
/
g
c
d
(
a
,
b
)
y
−
a
/
g
c
d
(
a
,
b
)
x+b/gcd(a,b) \ \ \ \ \ \ \ y-a/gcd(a,b)
x+b/gcd(a,b) y−a/gcd(a,b)代入式子得
a
x
+
a
∗
b
/
g
c
d
(
a
,
b
)
+
b
y
−
a
∗
b
/
g
c
d
(
a
,
b
)
=
m
ax+a*b/gcd(a,b)+by-a*b/gcd(a,b)=m
ax+a∗b/gcd(a,b)+by−a∗b/gcd(a,b)=m 这里是不是
a
x
+
b
y
=
m
ax+by=m
ax+by=m了 相当于这个式子加一个
a
,
b
a,b
a,b 的最小公倍数 然后又减去一个最小公倍数 。
那么特解就是
x
+
b
/
g
c
d
(
a
,
b
)
y
−
a
/
g
c
d
(
a
,
b
)
x+b/gcd(a,b)\ \ \ \ \ y-a/gcd(a,b)
x+b/gcd(a,b) y−a/gcd(a,b)
x
=
x
0
−
d
b
∗
k
x=x_0-\frac{d}{b}*k
x=x0−bd∗k
y = y 0 + d b ∗ k y=y_0+\frac{d}{b}*k y=y0+bd∗k