码迷,mamicode.com
首页 > 编程语言 > 详细

扩展欧几里得算法详解

时间:2018-10-19 19:21:05      阅读:748      评论:0      收藏:0      [点我收藏+]

标签:inline   打开   扩展   新解   应该   exgcd   扩展欧几里得算法   mat   算法详解   

本篇将附上扩展欧几里得算法的思想与推导;


对于一个方程\(a*x+b*y=gcd(a,b)\)来说,我们可以做如下的推导:

设有\(a*x_1+b*y_1=gcd(a,b)\);

同时我们有\(b*x_2+(a\%b)*y_2=gcd(b,a\%b)\);

对于这个方程组,我们希望知道的是\(x_1,x_2,y_1,y_2\)之间的关系,这样我们才可以递归解决这个问题;

我们观察\(b*x_2+(a%b)*y_2\)这个式子,我们可以将\((a\%b)\)写作\((a-\lfloor\frac{a}{b}\rfloor*b)\),将括号打开常数\(a,b\)合并,合并之后的结果为\(a*y_2+b*(x_2-\lfloor\frac{a}{b}\rfloor*y_2))\)

由于欧几里得算法的原理\(gcd(a,b)==gcd(b,a%b)\),我们将两式子联立,对比系数即可得到\(x_1=y_2,y_1=x_2-\lfloor\frac{a}{b}\rfloor*y_2\);

这个递归的边界是什么呢?我们知道,当朴素欧几里得到达边界时,\(return gcd(a,0)=a\),那么边界条件就是对\(a*x_0+b*y_0=a\)求解,很显然,此时\(x_0=1,y_0=0\);

当我们递归求出了一个方程的特解时,如何求出这个方程的通解呢?

方程\(a*x+b*y=gcd(a,b)\)中,如果将x加上一个常数\(k_1,y\)减去一个常数\(k_2\),仍然保持原方程成立,那么\(x+k_1,y-k-2\)就是方程的一个新解,这个k应该如何选择呢?

实际上很简单,\(a*(x+k_1)+b*(y+k_2)=gcd(a,b)\),打开括号,\(a*x+a*k_1+b*y-b*k_2=gcd(a,b)\),我们保证原方程成立,就需要\(a*k_1==b*k_2\),那么显然\(k_1=b,k_2=a\)是一种合理的情况,但是这样是无法包含所有整数解的,因为我们加上的这个值并非是最小值.

那我们应该加上什么值才行呢?我们发现当\(a*k_1==b*k_2=t*lcm(a,b)\)可以保证得到所有解,于是每次寻找解就可以分别在\(x\)加上\(\frac{b}{gcd(a,b)},在y减去\frac{a}{gcd(a,b)}\)就可以了

对于方程\(a*x+b*y=c\)我们又该如何求解?我们发现如果\((c%gcd(a,b)!=0)\)那么这个方程是无解的,而如果\(gcd(a,b)*t==c\),我们就可以按上面的方法求解之后对我们的解乘上一个\(t(t=\frac{c}{gcd(a,b)})\)

\(code:\)


int exgcd(int a,int b,int &x1,int &y1)
{
    if(!b)
    {
        x1=1,y1=0;
        return a;
    }
    int x2,y2;
    int d=exgcd(b,a%b,x2,y2);
    x1=y2,y1=x2-(a/b)*y2;
    return d;
}

扩展欧几里得算法详解

标签:inline   打开   扩展   新解   应该   exgcd   扩展欧几里得算法   mat   算法详解   

原文地址:https://www.cnblogs.com/KatouKatou/p/9818175.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!