zoukankan      html  css  js  c++  java
  • 扩展欧几里得算法

    给定两个正整数m和n,我们计算它们的最大公因子d和两个整数a和b,使得a*m+b*n=d

    算法流程

      E1.置a'=b=1;a=b'=0;c=m,d=n;

      E2.计算d和r,使得c=q*d+r;

      E3.若r==0;则退出,当前已有a*m+b*n=d;

      E4;c=d;d=r;t=a';a'=a;a=t-q*a;t=b';b'=b;b=t-q*b;返回E2.

    证明

     递归版本:

      对于已有的m和n,假设m>n;如果刨除变量a,b,a',b';算法与欧几里得算法完全一样,为计算最大公约数的算法.

      最终要求的为a*m+b*n=d=GCD(m,n);如果改式子成立由欧几里得算法可推出a'*n+b'*(m%n)=GCD(n,m%n);

      因为GCD(m,n)=GCD(n,m%n);

      所以a*m+b*n=a'*n+b'*(m%n)

            =a'*n+b'*(m-(m/n)*n)

            =a'*n+b'*m-b'*(m/n)*n

            =b'*m+(a'-b'*(m/n))*n

      所以a=b';b=a'-b'*(m/n);

      可以推出根据a‘、b'可以计算a、b。

      非递归版本:

      设m为r[0],n=r[-1];根据欧几里得算法可推出

      r[i-2]=r[i-1]*q[i]+r[i]; r=1...n+1;         (1)

      r[i](r=1...n+1)为每次迭代的余数,可知r[n+1]=0;且r[n]=GCD(m,n);

      由于每个r都是前两个r的组合,所以对于a*m+b*n=GCD(m,n)存在(可用数学归纳法证明):

      a[i]*m+b[i]*n=r[i];              (2)

      当i==1时,根据(1)(2)式

        a[1]*m+b[1]*n=r[1]

              =r[-1]-r[0]*q[1]

              =n-q[1]*m

      可推出:a[1]=-q[1],b[1]=1;

      当i==2时,根据(1)(2)式

        a[2]*m+b[2]*n=r[2]

              =r[0]-r[1]*q[2]

              =r[0]-(a[1]*m+b[1]*n)*q[2]

              =m-a[1]*q[2]*m-b[1]*q[2]*n

              =(1-a[1]*q[2])*m-b[1]*q[2]*n

      可推出:a[2]=1-a[1]*q[2],b[2]=-b[1]*q[2];

      当i>=3时,根据(1)(2)式

        a[i]*m+b[i]*n=r[i]

              =-q[i](a[i-1]*m+b[i-1]*n)+(a[i-2]*m+b[i-2]*n)

              =(-q[i]*a[i-1]+a[i-2])*m+(-q[i]*b[i-1]+b[i-2])*n

      对于i>=3,a[i]=-q[i]*a[i-1]+a[i-2],b[i]=-q[i]*b[i-1]+b[i-2];

      当我们定义:a[-1]=0,a[0]=1,b[-1]=1,b[0]=0时,可构造出a,b的公式

        a[-1]=0,a[0]=1,a[i]=-q[i]*a[i-1]+a[i-2](i>=1)

        b[-1]=1,b[0]=0,b[i]=-q[i]*b[i-1]+b[i-2](i>=1)

    代码实现

    void EGCD(int m,int n)
    {
        int a,a1,b,b1,c,d,q,r,t;
        a1=b=1,a=b1=0,c=m,d=n;
        while(1)
        {
            q=c/d,r=c%d;
            if(r==0)
            {
                printf("(%d)*%d+(%d)*%d=%d
    ",a,m,b,n,d);
                return;
            }
            c=d,d=r,t=a1,a1=a,a=t-q*a,t=b1,b1=b,b=t-q*b;
        }
    }
    View Code
  • 相关阅读:
    Android HandlerThread
    JavaScript数据类型
    Android:VideoView
    我是如何跟踪log4j漏洞原理及发现绕WAF的tips
    Dubbo的反序列化安全问题——kryo和fst
    使用移动硬盘快速安装win7(附BIOS设置)
    OpenStack Swift All In One安装部署流程与简单使用
    C语言浮点数运算
    使用注册表文件(REG)添加、修改或删除Windows注册表项和值
    Linux之TCPIP内核参数优化
  • 原文地址:https://www.cnblogs.com/NoSoul/p/3294502.html
Copyright © 2011-2022 走看看