数论入门_扩展欧几里得算法

EXGCD

学了扩展欧几里得算法好长时间了,打篇博客复习一下

具体推导与用法如下


拓展欧几里得算法

主要解决求解同余方程的问题

下面是一个关于x ,y的二元一次方程

  • ax + by = c

根据裴蜀定理 ,如果gcd(a,b) | c,则此方程存在整数解(充分必要条件)

因此我们仅当c=gcd(a,b)
所以 a$x_1$ + b$y_1$ = gcd(a,b)

通过欧几里得算法,可得
gcd(a,b)=gcd(b,a%b)

这时 在 a=b,b=a%b的条件下
bx_2 + a%b y_2 = gcd(b,a%b)

所以 :

  • ax_1 + by_1 = bx_2$ + (a%b)y_2

假设k=a/b(向下取整),r=a%b

那么 a = kb+r = b(a/b)+a%b,
a%b = r = a-kb = a-b(a/b)

bx_2 + (a%b)$y_2$

= bx_2 + (a-b(a/b))$y_2$

= bx_2 - b(a/b)y_2 + ay_2

=b(x_2 - (a/b)y_2) + ay_2

=ay_2 + b(x_2 - (a/b)y_2)

所以可得:

b$x_2$ + (a%b)$y_2$ = a$y_2$ + b($x_2$ - (a/b)$y_2$)

a$x_1$ + b$y_1$ = b$x_2$ + (a%b)$y_2$ = a$y_2$ + b($x_2$ - (a/b)$y_2$)

  • a$x_1$ + b$y_1$ = a$y_2$ + b($x_2$ - (a/b)$y_2$)

惊喜地发现:

  • $x_1$ = $y_2$ , $y_1$ = $x_2$ - (a/b)$y_2$

得到此递归转移公式后,开始打exgcd部分的代码

int exgcd(int a,int b,int &x1,int &y1) //附带求gcd的功能
{
    if(b==0){
        x=1;  //当 ax+by=gcd(a,b)中b=0时,a=gcd(a,b),x=1,y=0
        y=0;
        return a; //gcd功能实现,b=0时gcd(a,b)=a
    }
    int x2,y2;
    int t=exgcd(b,a%b,x2,y2);
    x1=y2;
    y1=x2-(a/b)*y2;
    return t;  //返回gcd(a,b)
}

特解求出了通解便也好求了

对于两个方程

a$x_1$ + b$y_1$ = $c_1$
, a$x_2$ + b$y_2$ = $c_2$

$x_1$=($c_1$/$c_2$)$x_2$ , $y_1$=($c_1$/$c_2$)$y_2$

所以此时回到在上面的方程

  • ax + by = c

x = $x_1$ ( c / gcd(a,b))

y = $y_1$ ( c / gcd(a,b))


完整代码

#include<iostream>
using namespace std;
int X,Y;
int x1,y1; 
int gcd(int a,int b)
{
    return b ?  gcd(b,a%b) : a;
}
int exgcd(int a,int b,int &x1,int &y1) //附带求gcd的功能
{
    if(b==0){
        x=1;  //当 ax+by=gcd(a,b)中b=0时,a=gcd(a,b),x=1,y=0
        y=0;
        return a; //gcd功能实现,b=0时gcd(a,b)=a
    }
    int x2,y2;
    int t=exgcd(b,a%b,x2,y2);
    x1=y2;
    y1=x2-(a/b)*y2;
    return t;  //返回gcd(a,b)
}

int main()
{
    int a,b,c;
    cin>>a>>b>>c;
    int l=c/exgcd(a,b,x1,y1);
    X=x1*l;
    Y=y1*l;
    cout<<X<<" "<<Y<<endl;
}

结束,蒟蒻鱼去补作业了

猜你喜欢

转载自www.cnblogs.com/XJack/p/10850148.html