• 欧几里德和扩展欧几里德详解 以及例题CodeForces 7C


    欧几里德定理:

    对于整数a,b来说,gcd(a, b)==gcd(b, a%b)==d(a与b的最大公约数),又称为辗转相除法

    证明:

    因为a是d的倍数,b是d的倍数;所以a%d==0;b%d==0;

    设k=a/b;r=a%b;则 a=k*b+r; 

    由上得出:r=a-k*b;

    因为a和b都是d的倍数,所以(a-k*b)也是d的倍数,所以r也是d的倍数;

    所以gcd(a, b)==gcd(b, a%b)==d

    而为什么要证明gcd(a, b)==gcd(b, a%b)==d这个式子成立呢?

    其实证明gcd(a, b)==gcd(a, a%b)==d这个式子成立也是可以的,因为a也是d的倍数,但是在进行递归之前要进行一步操作,就是判断a与b的大小,如果a<b,就没办法进行递归或者循环求最大公约数,那么如果a<b,就交换a与b,之后就不用交换了,因为已知a>b,那么a%b<a必定成立;

    事实发现证明gcd(a, b)==gcd(b, a%b)==d这个式子会缩小处理的数据的范围;

    欧几里德应用:

    用来求a,b的最大公约数。

    代码实现:

    //gcd(a, b)==gcd(a, a%b)==d,也成立
    #include<stdio.h>
    int main()
    {
        int m, n, r, t;
        scanf("%d%d", &m, &n);
        if(m<n)
        {
            t=m;
            m=n;
            n=t;
        }
        while(r=m%n, r!=0)
        {
            m=m;
            n=r;
        }
        printf("%d
    ", n);
        return 0;
    }
    

      

    //gcd(a, b)==gcd(a, a%b)==d递归
    int gcd(int m, int n)
    {
        return n?gcd(n, m%n):m;
    }
    

      

    //gcd(a, b)==gcd(a, a%b)==d递归
    int gcd(int m, int n) { if(m%n==0) return n; else return gcd(n, m%n); }

      

    //gcd(a, b)==gcd(b, a%b)==d 循环
    while((r=m%n)!=0)
    {
      m=n;
      n=r;
    }
    

    扩展欧几里德定律: 

    对于不完全为0的非负整数a,b;gcd(a, b)表示a, b的最大公约数,必定存在整数对x,y,满足a*x+b*y==gcd(a, b);

    证明:

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

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

    因为由欧几里德定理知:gcd(a, b)==gcd(b, a%b)

    所以a*x1+b*y1=b*x2+(a%b)*y2;     因为r=a%b,   r =a-k*b所以==>

    a*x1+b*y1=b*x2+(a-k*b)*y2;         因为k=a/b;所以 ==>

    a*x1+b*y1=b*x2+(a-(a/b)*b)*y2;     展开得到  ==>    

    a*x1+b*y1=b*x2+a*y2-b*(a/b)*y2;  转换得到      ==>

    a*x1+b*y1=a*y2+b*(x2+(a/b)*y2);

    观察上式可知 x1=y2, y1=x2-a/b*y2;

    由此可知x1,y1是由x2,y2得出来的,由此类推x2,y2是由x3,y3得出来的,

    那什么时候是终止呢?也就是递归gcd(a, b)中b=0时;也就是说此时a的值就是要求得最大公约数

    即gcd(a, 0)此时由扩展欧几里得定律a*x+b*y==gcd(a, b)知 a*x+b*y=a;

    解出x=1, y=0;

    此时就是递归终止的地方:

    扩展欧几里德应用:

    就我目前所知的就是:求解不定方程;如a*x+b*y=c; 已知a, b, c的值求x和y的值

    那么问题来了,如何将扩展欧几里德定律应用在求解不定方程呢?

    可以这样转化   a*x+b*y=gcd(a, b)*c/gcd(a, b);

    最后转化为 a*x/(c/gcd(a, b))+b*y/(c/gcd(a, b))=gcd(a, b); 最后求出的解x0,y0乘上c/gcd(a, b)就是最终的结果了

    x1=x0*c/gcd(a, b);

    y1=y0*c/gcd(a, b);

    代码实现:  举例说明:http://codeforces.com/problemset/problem/7/C

    #include<stdio.h>
    long long exgcd(long long a, long long b, long long &x, long long &y);
    int main()
    {
        long long a, b, c, ans, x, y;
    
        while(scanf("%lld%lld%lld", &a, &b, &c)!=EOF)
        {
            ans=exgcd(a, b, x, y);
            if(c%ans==0)
            {
                x=-x*c/ans;
                y=-y*c/ans;
                printf("%lld %lld
    ", x, y);
            }
            else
                printf("-1
    ");
        }
        return 0;
    }
    long long exgcd(long long a, long long b, long long &x, long long &y)
    {
        if(b==0)
        {
            x=1;
            y=0;
            return a;
        }
        long long r=exgcd(b, a%b, x, y), t;
        t=x;
        x=y;
        y=t-(a/b)*y;
        return r;
    }
    

     但这只是求得了一组解x1,y1

    对于x,y对应的解集是:

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

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

    但是我证明不出来,如果哪位大神懂得,可以给我说说!

  • 相关阅读:
    局部加权回归-新的回归思路,为每个样本订制个性化的模型
    Java Spring AOP
    Spring IOC DI 注解开发
    Java Spring IoC
    Pytest自动化测试
    Robot Framework 实现并行测试
    【解决】cannot list resource "services" in API group "" in the namespace "jmbymt"
    Pytest自动化测试
    Kube-prometheus监控jmx指标
    Pytest自动化测试
  • 原文地址:https://www.cnblogs.com/wazqWAZQ1/p/4919592.html
Copyright © 2020-2023  润新知