欧几里得算法

【辗转相除法求GCD】

欧几里得法求GCD效率较辗转相减法求GCD而言效率要高得多。

算法原理:gcd(a,b)=gcd(b,a mod b)

首先我们可以假设a=kb+ra=k∗b+r(其中的r代表着a/b的余数,也就是a%b的结果)

  1.首先我们假设d是a和b的最大公约数,则我们可以知道 a可以整除d,表示为a|b,b也可以整除d,表示为b|d,由于r=akbr=a−k∗b 其中a是d的倍数,而且b也是d的倍数,那我们可以得到其实r也是d的倍数,换句话说r也是可以整除d.

  2.接下来我们假设d是b和r的最大公约数,则我们可以知道b可以整除d,表示为b|d,r也可以整除d,表示为r|d,由于a=kb+ra=k∗b+r其中b是d的倍数,而且r也是d的倍数,那我们可以得知其实a也是d的倍数,换句话说a也是可以整除d.

通过以上的充分必要式的证明方法,我们可以得到:gcd(a,b)=gcd(b,a%b)

【gcd模板】

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

【扩展欧几里得算法】

解决问题:ax + by = gcd(a,b)的一组整数解x0 y0

算法原理:

(1)当b = 0时,很显然 x = 1,y = 任意整数。不妨x = 1, y = 0

(2)设 bx' + (a%b) y' = gcd(b , a%b)

由欧几里得算法:gcd(a,b)=gcd(b,a%b)

从而:ax + by = bx' + (a%b) y'; 即 ax + by = bx' + (a - a/b*b)y'

整理成关于a,b的不定方程:ax + by = ay' + b(x' - a/by'),系数对应相等得到:

x = y' ;

y = x' - a/by'

试想:如果不断迭代下去,直至b = 0,然后运用(1)的结果直接得到(x' = 1, y '= 0)反推回去,是不是就能够得到初始的x,y的值了?

int ex_gcd(int a,int b,int &x,int &y)
{
    if(b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    int r = ex_gcd(b,a%b,x,y);
int t = x;//保存上一次的x' x = y;//本次的x是上一次的y' y = t - a/b*y;//本次的y是上一次的x' - a/b*y'
return r; }

【定理总结】

(1)二元一次不定方程 ax + by = k有解的充要条件是 gcd(a,b) | k

(2)若ax + by = gcd(a,b)的一组特解是x0 ,y0,则通解:

x = x0 + b/gcd(a,b) * t ;

y = y0 -  a/gcd(a,b) * t ,

方程ax + by = k的解是x,y乘上 k/gcd(a,b),即x = (x0 + b/gcd(a,b) * t) * k/gcd(a,b)

(3)要求方程ax + by = k的x的最小正整数解,则先求一个x0,y0,令p = b/gcd(a,b) 

然后令 x = (x0 + p)* k/gcd(a,b), x = (x%p + p)%p.对应的y =(k - a*x) / b

【例题】

poj2142

原文地址:https://www.cnblogs.com/czsharecode/p/9736800.html