扩展欧几里得应用分析

原理推导:

    首先我们定义:设a和b不全为0,则存在整数x和y,使得gcd(a,b)=ax+by。这就是扩展欧几里得的算法描述。

    扩展欧几里得算法是用来求解二元一次方程。对于方程Ax+By=C,其中A,B,C为整数,求出满足等式的整数x和y。考虑到给出的方程不一定是最简形式,所以我们需要先化为最简式,设d=gcd(A,B),那么化简后的方程为:ax+by=c,其中a=A/d,b=B/d,c=C/d;

    此时,gcd(a,b)=1,先将方程ax+by=gcd(a,b)=1解出后,设x0,y0为方程的特解,那么原方程的最终解为c*x0,c*y0.现在问题来了,怎么求方程ax+by=1的解呢?这就是我们要讨论的扩展欧几里得了。

    扩展欧几里得是求方程ax+by=gcd(a,b)的解。设a>b,当b=0时,gcd(a,b)=a,此时x=1,y=0;否则我们设:

        a*x1+b*y1=gcd(a,b);

        b*x2+(a mod b)*y2=gcd(b,a mod b);

    在欧几里得算法中,我们有gcd(a,b)=gcd(b.a mod b),所以我们进一步得到:

        a*x1+b*y1 = b*x2+(a mod b)*y2 = b*x2+(a-|_ a/b _|*b)*y2 = a*y2+b*(x2-|_ a/b _|*y2);

    所以有:x1=y2;    y1=x2-|_ a/b _|*y2;

    举个例子来说吧,考虑二元一次方程48x+30y=gcd(48,30),我们先通过欧几里得递归求出它们的最大公约数6,然后逐层回溯得到x和y:

递归过程:48=1×30+18

          30=1×18+12

          18=1×12+6

          12=2×6+0

回溯过程:6=18-(1×12)

           =18-1×(30-18×1)

           =18-1×(30-(48-30×1)×1)

           =48×2-30×3

递归实现代码如下:

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



非递归实现代码如下:

typedef long long LL;
LL exgcd(LL m,LL &x,LL n,LL &y)
{
    LL x1,y1,x0,y0;
    x0=1;x1=0;
    y0=0;y1=1;
    LL r=(m%n+n)%n;
    LL t=(m-r)/n;
    x=0;y=1;
    while(r)
    {
        x=x0-t*x1;
        y=y0-t*y1;
        x0=x1;y0=y1;
        x1=x;y1=y;
        m=n;n=r;r=m%n;
        t=(m-r)/n;
    }
    return n;
}



应用与分析:

    上面讲了扩展欧几里得算法的原理,通过这个方法可以得到二元一次方程的特解,实际上,得到特解之后,就可以得到通解,如下:

    x=c*x0-b*t;

    y=c*y0+a*t;

其中t∈Z,将上述解代入方程,有:

    ax+by=a*(c*x0-b*t)+b*(c*y0+a*t)=a*c*x0+b*c*y0=(a*x0+b*y0)*c=c;


在ACM中,扩展欧几里得的应用主要包括:

(1)求解不定方程;

(2)求解模的逆元;

(3)求解同余方程;


例题:

POJ1061µhttp://poj.org/problem?id=1061

http://acm.hit.edu.cn/hoj/problem/view?id=2815

http://poj.org/problem?id=2142

http://codeforces.com/problemset/problem/7/C

你可能感兴趣的:(扩展欧几里得应用分析)