证明欧几里德算法的关键是要证明 g c d ( a , b ) = g c d ( b m o d a , a ) gcd(a,b)=gcd(b\ mod \ \ a,a) gcd(a,b)=gcd(b mod a,a)
b m o d a 等 价 于 b − ⌊ b / a ⌋ × a b\ mod\ \ a 等价于 b - ⌊b/a⌋ \times a b mod a等价于b−⌊b/a⌋×a
b − ⌊ b / a ⌋ × a 能 被 g c d ( a , b ) 整 除 b - ⌊b/a⌋ \times a 能被 gcd( a , b )整除 b−⌊b/a⌋×a能被gcd(a,b)整除
又 因 为 a 和 b 都 能 被 g c d ( a , b ) 整 除 又因为 a 和 b 都能被 gcd( a , b )整除 又因为a和b都能被gcd(a,b)整除
所 以 b m o d a 和 a 也 能 被 g c d ( a , b ) 整 除 所以 b \ mod \ \ a 和 a 也能被 gcd( a , b )整除 所以b mod a和a也能被gcd(a,b)整除
int gcd(int a,int b){
return b==0?a:gcd(b,a%b);
}
如果a和b都是整数,则有整数x和y 使得 a x + b y = G C D ( a , b ) ax+by=GCD(a,b) ax+by=GCD(a,b)
推论 若a,b互素,则存在x和y使得 a x + b y = 1 ax+by=1 ax+by=1
设c是a和b的线性组合中最小整数
a x + b y = c ( x , y 为 整 数 ) ax+by=c (x,y 为整数) ax+by=c(x,y为整数)
令 a = c q + r ( 0 ≤ r < c ) a=cq+r (0\leq r<c) a=cq+r(0≤r<c)
可得 r = a − c q = a ( 1 − q x ) − b q y r=a-cq=a(1-qx)-bqy r=a−cq=a(1−qx)−bqy
所以 r 是 a 和 b 的线性组合
又因为 c是a和b的线性组合中最小整数
所以 r == 0
所以 c 是 a 的约数
同理 c 是 b 的约数
所以 c 是 a 和 b 的公约数
对于 a 和 b 的所有约数 d
因为 ax + by = c
所以 d 是 c 的约数 c ≥ d c\geq d c≥d;
所以 c 是 最大公约数 G C D ( a , b ) GCD (a , b) GCD(a,b)
因 为 a x 1 + b y 1 = G C D ( a , b ) , a x 2 + G C D ( b , a % b ) y 2 = G C D ( b , a % b ) = G C D ( a , b ) 因为 a x_1+b y_1=GCD(a,b) , a x_2+GCD(b,a\%b) y_2=GCD(b,a\%b)=GCD(a,b) 因为ax1+by1=GCD(a,b),ax2+GCD(b,a%b)y2=GCD(b,a%b)=GCD(a,b)
所 以 a x 1 + b y 1 = b x 2 + ( a − ⌊ a / b ⌋ ∗ b ) y 2 = a y 2 + b ( x 2 − ⌊ a / b ⌋ ∗ y 2 ) 所以 a x_1+b y_1=b x_2+(a - ⌊a/b⌋ *b) y_2=a y_2 + b(x_2-⌊a/b⌋ * y_2) 所以ax1+by1=bx2+(a−⌊a/b⌋∗b)y2=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
重 复 这 一 过 程 直 到 b = = 0 此 时 x = 1 , y = 0 。 重复这一过程 直到 b==0 此时 x=1,y=0。 重复这一过程直到b==0此时x=1,y=0。
x 1 = y 2 x_1=y_2 x1=y2
y 1 = x 2 − ⌊ a / b ⌋ ∗ y 2 y_1=x_2 - ⌊a/b⌋ * y_2 y1=x2−⌊a/b⌋∗y2
当c是gcd(a,b)的倍数时
x = x 0 + k ∗ ⌊ b / g c d ( a , b ) ⌋ x=x_0+k*⌊b/gcd(a,b)⌋ x=x0+k∗⌊b/gcd(a,b)⌋
y = y 0 − k ∗ ⌊ a / g c d ( a , b ) ⌋ y=y_0-k*⌊a/gcd(a,b)⌋ y=y0−k∗⌊a/gcd(a,b)⌋
若c不是gcd(a,b)的倍数时
则 a x + b y = c ax+by=c ax+by=c无整数解
int exgcd(int a,int b,int &x, int &y){
if(b==0){ x=1,y=0;return a;}
int t=exgcd(b,a%b,x,y);
int x0=x,y0=y;
x=y0,y=x0-(a/b)*y0;
return t;
}
&是引用的符号,一变全变
https://cn.vjudge.net/problem/HDU-2669
#include
#define ll long long
using namespace std;
ll exgcd(ll a,ll b,ll &x, ll &y){
if(b==0){ x=1,y=0;return a;}
ll t=exgcd(b,a%b,x,y);
ll x0=x,y0=y;
x=y0,y=x0-(a/b)*y0;
return t;
}
int main(){
ll a,b,x,y;
while(cin>>a>>b){
if(exgcd(a,b,x,y)==1){
int c=exgcd(a,b,x,y);
while(x<=0){
x=x+b/c;
y=y-a/c;
}
cout<<x<<" "<<y<<endl;
}
else cout<<"sorry"<<endl;
}
return 0;
}
https://cn.vjudge.net/problem/POJ-2142
#include
#include
using namespace std;
int exgcd(int a,int b,int &x, int &y){
if(b==0){ x=1,y=0;return a;}
int t=exgcd(b,a%b,x,y);
int x0=x,y0=y;
x=y0,y=x0-(a/b)*y0;
return t;
}
int main(){
int a,b,d,x,y;
while(~scanf("%d %d %d", &a, &b, &d)&&(a||b||d)){
int md=exgcd(a,b,x,y);
a/=md,b/=md,d/=md;
int x1=x*d;
x1=(x1%b+b)%b;
int y1=(d-x1*a)/b;
y1=abs(y1);
int y2=y*d;
y2=(y2%a+a)%a;
int x2=(d-y2*b)/a;
x2=abs(x2);
if(x1+y1<x2+y2) printf("%d %d\n",x1,y1);
else printf("%d %d\n",x2,y2);
}
return 0;
}
https://cn.vjudge.net/problem/ZOJ-3593
#include
#include
#define INF 0x3fffffff
using namespace std;
long long exgcd(long long a,long long b,long long &x, long long &y){
if(b==0){ x=1,y=0;return a;}
long long t=exgcd(b,a%b,x,y);
long long x0=x,y0=y;
x=y0,y=x0-(a/b)*y0;
return t;
}
long long abs1(long long a){
if(a<0) return -a;
return a;
}
long long judge(long long x,long long y){
if(abs1(x+y)!=abs1(x)+abs1(y)) return abs1(x)+abs1(y);
return max(abs1(x),abs1(y));
}
int main(){
long long A,B,a,b,d,x,y;
int T;
scanf("%d", &T);
while(T--){
scanf("%lld %lld %lld %lld", &A, &B, &a, &b);
long long md=exgcd(a,b,x,y);
d=abs1(B-A);
if(d%md!=0){
printf("-1\n");
continue;
}
a/=md,b/=md;
x*=d/md;
y*=d/md;
long long mid = (y - x) / (a + b);//当x和y最接近的时候,|x|+|y|最小
long long ans = (long long)INF * (long long)INF;
for(long long t=mid-2;t<=mid+2;t++){
ans=min(ans,judge(x+b*t,y-a*t));
}
printf("%lld\n", ans);
}
}