扩展欧几里得
问:如何求得一组 x , y x,y x,y,使得 A x + B y = C Ax+By=C Ax+By=C成立。
假设上式成立,首先令 g = g c d ( A , B ) g=gcd(A,B) g=gcd(A,B),那么上式就可以写成 k 1 g x + k 2 g y = C k_1gx+k_2gy=C k1gx+k2gy=C,化简得, g ( k 1 x + k 2 y ) = C g(k_1x+k_2y)=C g(k1x+k2y)=C,说明 C % g C\%g C%g=0 。所以 A x + B y = C Ax+By=C Ax+By=C存在解得条件就是 C % g C\%g C%g=0;反之,则不存在。
根据数论中相关定理,存在x,y,满足:
A
x
+
B
y
=
g
c
d
(
A
,
B
)
Ax+By=gcd(A,B)
Ax+By=gcd(A,B)。
怎么求一组解呢?
A
x
1
+
B
y
1
=
g
c
d
(
A
,
B
)
Ax_1+By_1=gcd(A,B)
Ax1+By1=gcd(A,B)·················································································1
B
x
2
+
(
A
%
B
)
y
2
=
g
c
d
(
B
,
A
%
B
)
Bx_2+(A\%B)y_2=gcd(B,A\%B)
Bx2+(A%B)y2=gcd(B,A%B)
B
x
2
+
(
A
−
(
A
/
B
)
∗
B
)
y
2
=
g
c
d
(
B
,
A
%
B
)
Bx_2+(A-(A/B)*B)y_2=gcd(B,A\%B)
Bx2+(A−(A/B)∗B)y2=gcd(B,A%B)····················································2
1,2式等式左边相等:
A
x
1
+
B
y
1
=
B
x
2
+
(
A
−
(
A
/
B
)
∗
B
)
y
2
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
=
A
y
2
+
B
(
x
2
−
(
A
/
B
)
y
2
)
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 , y 1 = x 2 − ( A / B ) y 2 x_1=y_2,y_1=x_2-(A/B)y_2 x1=y2,y1=x2−(A/B)y2。下面给出代码
long long exgcd(long long a,long long b,long long &x,long long &y)
{
if(b==0){
x=1,y=0;//如果b==0,那么gcd(A,B)=A,那么x=1,y=0
return a;
}
long long ans=exgcd(b,a%b,x,y);
int temp=x;//下面这三句之所以要放在递归调用和return之间是因为要根据后面递归算出来的x,y值才能推出最开始的x,y
x=y;//(接上一行注释)也就是Ax+By=gcd(A,B)的解
y=temp-(a/b)*y;
return ans;
}
执行完这段程序后就可以得到一组特解x,y。那么怎么求通解呢,下面给出证明:
通解:
x
=
x
0
+
B
g
c
d
(
A
,
B
)
∗
t
x=x_0+\frac{B}{gcd(A,B)}*t
x=x0+gcd(A,B)B∗t
y
=
y
0
−
A
g
c
d
(
A
,
B
)
∗
t
y=y_0-\frac{A}{gcd(A,B)}*t
y=y0−gcd(A,B)A∗t
t为整数
就写道这吧。以后发现不足再改。
例题:
A line on the plane is described by an equation Ax + By + C = 0. You are to find any point on this line, whose coordinates are integer numbers from - 5·1018 to 5·1018 inclusive, or to find out that such points do not exist.
Input
The first line contains three integers A, B and C ( - 2·109 ≤ A, B, C ≤ 2·109) — corresponding coefficients of the line equation. It is guaranteed that A2 + B2 > 0.
Output
If the required point exists, output its coordinates, otherwise output -1.
Examples
Input
2 5 3
Output
6 -3
模板扩展欧几里得题:
代码:
#include<cstdio>
#include<set>
#include<map>
#include<string.h>
#include<string>
#include<vector>
#include<iostream>
#include<queue>
#include<algorithm>
typedef long long LL;
using namespace std;
const int maxn=1e6+5;
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(b==0){
x=1,y=0;
return a;
}
LL ans=exgcd(b,a%b,x,y);
LL temp=x;
x=y;
y=temp-(a/b)*y;
return ans;
}
int main()
{
LL a,b,c,x,y;
scanf("%lld%lld%lld",&a,&b,&c);
LL g=exgcd(a,b,x,y);
if((-c)%g!=0){
printf("-1\n");
}
else {
LL ansx=x*(-c/g);
LL ansy=y*(-c/g);
printf("%lld %lld\n",ansx,ansy);
}
return 0;
}
下面再补充一点求通解和最小正整数的解的代码
#include<cstdio>
#include<set>
#include<map>
#include<string.h>
#include<string>
#include<vector>
#include<iostream>
#include<queue>
#include<algorithm>
typedef long long LL;
using namespace std;
const int maxn=1e6+5;
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(b==0){
x=1,y=0;
return a;
}
LL ans=exgcd(b,a%b,x,y);
LL temp=x;
x=y;
y=temp-(a/b)*y;
return ans;
}
int main()
{
LL a,b,c,x,y;
scanf("%lld%lld%lld",&a,&b,&c);
LL g=exgcd(a,b,x,y);
if((-c)%g!=0){
printf("-1\n");
}
else{
LL ansx=x*(-c/g);
LL ansy=y*(-c/g);
LL ta=b/g;
LL tb=a/g;
for(LL i=1;i<=100;i++){//枚举许多组解的过程
x=ansx+i*ta;
y=ansy-i*tb;
printf("%lld %lld\n",x,y);
cout<<(x*a+y*b+c==0)<<endl;
}
x=ansx+10*ta;//假设随意一组解,求x,y的最小正整数解
y=ansy-10*tb;
x=(x%ta-ta)%ta;
y=(y%tb+tb)%tb;//y的最小正整数解
x=(x%ta+ta)%ta;//x的最小正整数解
y=(y%tb-tb)%tb;
printf("%lld %lld\n",x,y);
}
return 0;
}