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

    内容:已知a, b,求解一组x,y,使它们满足贝祖等式: ax+by =gcd(a, b)

    扩展欧几里得算法,就和它的名字一样是对欧几里得算法的扩展。何为扩展?一是,该算法保留了欧几里得算法的本质,可以求a与b的最大公约数。二是,已知a, b求解二元一次方程ax+by =gcd(a, b)的一组解(x,y)。

    证明:

    假设 a>b,

    (1)  b=0  gcd(a,b) = a ,  ax = a ,  则x=1,y=0;(这里我还是推荐不把gcd(a,0)理解成最大公约数,而是一个计算机求出来的值)

    (2) 假设 ax1+by1=gcd(a,b) (方程一) bx2+(a%b)y2=gcd(b,a%b)(方程二);由欧几里得算法gcd(a,b) =gcd(b,a%b) 得到,

    ax1+by1 = bx2+(a%b)y2,即ax1+by1=bx2+(a-a/b*b)y2 ax1+by1=ay2+b(x2-a/b*y2)

    在根据多项式恒等定理(把a,b看成变量),x1=y2; y1=x2-a/b*y2;

    (表面上看,就是已知方程一的一组解,可以得到方程二的一组解,已知方程二的一组解,就可以得到方程一的一组解,但是实际情况是,不可能先知道方程一的解(x1,y1)。)上述思想是递归定义的,不断地利用gcd(a,b) =gcd(b,a%b),到b=0(y的系数为0)时,由(1)的解,根据解之间的关系,最终可以得到方程ax+by =gcd(a, b)的解。

    递归形式代码:

    #include<iostream>
    using namespace std;
    int exgcd(int a,int b,int &x,int &y)
    {
        if(b==0)//这里跟欧几里得算法一样
        {
            x=1;
            y=0;
            return a;
        }
        int gcd=exgcd(b,a%b,x,y);
        int x2=x;//这里是推的公式
        int y2=y;
        x=y2;
        y=x2-(a/b)*y2;
        return gcd;
    }
    int main()
    {
        int x,y,a,b;
        cin>>a>>b;
    
        cout<<"a b的最大公约数是:"<<exgcd(a,b,x,y)<<endl;
        cout<<"ax+by=gcd(a,b) 的一组解是:"<<x<<","<<y<<endl;
        /*
        那么我们要求很多组解怎么办呢?
        有两个公式
        x1=x2+k*b1  (b1=b/gcd(a,b)
        y1=y2-k*a1  (a1=a/gcd(a,b)
        */
        
        return 0;
    }

    如果要求多个解也很简单 :

    假设求出了ax+by=gcd(a,b)的一组解 x1,y1  假设第二组解为x2,y2  则ax1+by1=ax2+by2(因为他们都等于gcd(a,b))   变形得a(x1-x2)=b(y2-y1)  假设gcd(a,b)=g   方程两边同除以g

    得a1(x1-x2)=b1(y2-y1)  其中a1=a/g   b1=b/g   注意此时a1与b1互素  因此x1-x2一定是b1的整数倍(因为要想两者相等 一定要把b1约掉)设(x1-x2)为kb1   所以有y2-y1=ka1  

    所以就得到下面的公式了

    x1=x2+k*b1 (b1=b/gcd(a,b)
    y1=y2-k*a1 (a1=a/gcd(a,b)   这样就可以求得多个解了。

    当题目中要求我们求ax+by=c时  这个怎么求呢?  很简单  求得ax+by=gcd(a,b)的一组解 然后乘以c/gcd(a,b)就行了    如果c/gcd(a,b)不为整数 则没有整数解!!

    #include<iostream>
    using namespace std;
    int exgcd(int a,int b,int &x,int &y)
    {
        if(b==0)//这里跟欧几里得算法一样
        {
            x=1;
            y=0;
            return a;
        }
        int gcd=exgcd(b,a%b,x,y);
        int x2=x;//这里是推的公式
        int y2=y;
        x=y2;
        y=x2-(a/b)*y2;
        return gcd;
    }
    int main()
    {
        int x,y,a,b;
        cin>>a>>b;
    
        cout<<"a b的最大公约数是:"<<exgcd(a,b,x,y)<<endl;
        cout<<"ax+by=gcd(a,b) 的一组解是:"<<x<<","<<y<<endl;
    
        /*
        那么我们要求很多组解怎么办呢?
        有两个公式
        x1=x2+k*b1  (b1=b/gcd(a,b)
        y1=y2-k*a1  (a1=a/gcd(a,b)
        */
    
        int c;
        cin>>c;
        double z=1.0*c/exgcd(a,b,x,y);
        cout<<"ax+by=c 的一组解是:"<<x*z<<","<<y*z<<endl;
        return 0;
    }
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    js 匿名函数的链式调用
    mysql 数据库操作的一般操作命令
    js 截取一定数量的字节
    js 截取10个字节
    BootStrap入门教程 (四)
    安装Dedecms遇到的一系列问题
    BootStrap入门教程 (三)
    dedecms标签调用大全
    artDialog皮肤引入方式
    织梦cms安装完成后登录后台出现空白。主要原因是php版本的问题
  • 原文地址:https://www.cnblogs.com/caijiaming/p/10335592.html
Copyright © 2011-2022 走看看