扩展欧几里德算法

扩展欧几里德算法已经搞了好几天了,今天终于看明白,小做总结。

讲扩展欧几里得算法之前,先讲欧几里得算法和贝祖定理。

欧几里得算法

欧几里得算法就是辗转相除法,即gcd(a,b)=gcd(b,a%b)。

简单证明一下:

r=gcd(a,b),a=nr,b=mr。

a%b=(n-n/m*m)r。

因为gcd(n,m)=1。

设w=n/m。

则gcd(m,n-w*m)=1。

所以gcd(m,n-n/m*m)=1。

那么gcd(b,a%b)=1。

上代码。

int gcd(int a,int b){
    if(b==0){
        return a;
    }
    return gcd(b,a%b);
}

贝祖定理

a,b是整数,c=gcd(a,b),对于任意整数x,y,a*x+b*y是c的倍数。

今天我们运用的是当gcd(a,b)|c时,关于x,y的不定方程a*x+b*y=c(a,b,c均为整数)有整数解无数个。

下面是证明:

设r=gcd(a,b)。

a=nr,b=mr,c=qr。

y=(c-a*x)/b=(qr-nr*x)/mr=(q-n*x)/m。

当x为整数时,y为整数。

反之,当c不是gcd(a,b)的倍数时,q不为整数,则当x为整数时,y不为整数,当y为整数时,x不为整数。

扩展欧几里德算法

下面就是今天的重点——扩欧。

扩欧一般是用来解决不定方程(a*x+b*y=c(a,b,c为整数常数))整数解的问题的。

首先第一步,是根据贝祖定理判断有无整数解(gcd(a,b)|c则有整数解)。那么c=n*gcd(a,b),则设x=n*q,y=n*p。所以a*q+b*p=gcd(a,b)。

接着是第二步,是运用欧几里得算法得到a*q+b*p=gcd(a,b)=gcd(b,a%b)=b*q`+(a-a/b*b)*p`=a*p`+b*(q`-a/b*p`)。

再得到递归式,q=p`,p=q`-a/b*p`,从而推出q,p的一组整数解,*n可得x,y的一组整数解,最终整数解有x-k(b/gcd(a,b)),y+k(a/gcd(a,b)),因为k有无数个,所以整数解由无数个。

上代码。

 

#include<iostream>
using namespace std;
int x,y;
int exgcd(int a,int b){
    if(b==0){
        x=1;y=0;
        return a;
    }
    int w=exgcd(b,a%b);
    int k=x;
    x=y;
    y=k-a/b*y;
    return w;
}
int main(){
    int a,b,c;
    cin>>a>>b>>c;
    int w=exgcd(a,b);
    if(c%w!=0){
        cout<<"No";
    }
    else{
        cout<<x*c/w<<" "<<y*c/w;
    }
    return 0;
}

 

posted @ 2022-01-28 14:47  zzzzzz2  阅读(77)  评论(0编辑  收藏  举报