欧几里得算法和拓展欧几里得

    1:欧几里得算法,既辗转相除法。用于计算正整数a,b的最大公约数。举个例子,简单明了:

     12/8==1.....4

     8/4==2......0

     4/0==0 ,除数为0,终止,被除数为答案:4

       除数和余数反复做%运算,其实和/没什么关系了,直接看%就可以了,所以有递归代码:

ll gcd(ll a,ll b)
{
    return b?gcd(b,a%b):a;
}

      最小公倍数求解:a,b的最小公倍数等于a,b的乘积除以a,b的最大公约数:

cout<<x/gcd(x,y)*y<<endl;

     2:拓展欧几里得算法:参考自:https://blog.csdn.net/destiny1507/article/details/81750874,感谢大佬!

      首先有贝祖定理:a,b为整数,那么一定存在x,y使得a*x+b*y==gcd(a,b)。也可以说,a*x+b*y==m,那么m一定是gcd(a,b)的若干倍,可以用来判断方程是否有解。如何求x,y?这就是拓展欧几里得可以解决的一个问题了。

      如果辗转相除法到达了最底层:即a%b==0,此时a*x+b*y==gcd(a,b),x==1,y==0。此时的a,b已经不是初始的a,b了,要想得到初始a,b的x,y,需要递归到最底层再一层层往上推各个层次的x,y,直到第一层。递归算法中,是先得到下一个状态值。

      所以算a,b的x,y,假设下一层b,a%b得到了gcd,这个下一层是满足:b*x1+a%b*y1==gcd。对于a%b,有:a%b=a-(a/b)*b。所以原式为:

      b*x1+(a-a/b*b)*y1=a*y1+b*(x1-a/b*y1)。

      所以:x==y1,y==(x1-a/b*y1)。y1,x1均来源于下一层,所以通过递归先得到下一层,然后根据式子推出当前一层,直到得到原a,b的x,y来。

ll x,y,a,b;
void exgcd(ll a, ll b)
{
    if(b==0)
    {
        x=1;
        y=0;
        return ;
    }
    exgcd(b,a%b);
    ll t=x;
    x=y;
    y=t-a/b*y;
    return ;
}

 

posted @ 2020-04-28 23:03  liyexin  阅读(196)  评论(0编辑  收藏  举报