• 扩展欧几里得算法


    1 欧几里得算法标准代码

    这个代码算的是符合a * x + b * y = gcd(a, b)的一组x, y, 同时返回了gcd(a, b)

    因为a * x1 + b * y1 = gcd(a, b)

      gcd(a, b) = gcd(b, a % b)

    那么a * x1 + b * y1 = gcd(b, a % b) = b * x2 + (a - a/b*b) * y2;   // a % b = a - a/b*b;而且x2, y2是更内层的

    把上面得到的式子变形得 a * x1 + b * y1 = a * y2 + b * (x2 - a / b * y2);  

             对应x1 = y2, y1 = x2 - a / b * y2;

    里面一层有返回值的时候想着返回上一层就好理解了,比如对应x1 = y2, y1 = x2 - a / b * y2;可以理解为上一层的y2赋给这一层的x1,上一层的 x2 - a / b * y2赋给y1

    __int64 exGcd(__int64 a,__int64 b,__int64 &x,__int64 &y)
    {
        if(b==0){
            x=1;
            y=0;
            return a;
        }
        __int64 g=exGcd(b,a%b,x,y);
        __int64 temp=x;
        x=y;
        y=temp-(a/b)*y;
        return g;
    }

    2求 a * x + b * y = c的解

    就是根据上面模板算出gcd(a, b)的同时算出a * x + b * y = gcd(a, b)的解,

    然后x = x * c / gcd(a, b);   y = y * c / gcd(a, b);

    其中,a*x+b*y = c有整数解的充要条件是gcd(a, b)|c;

    #include <cstdio>
    __int64 exGcd(__int64 a,__int64 b,__int64 &x,__int64 &y)
    {
        if(b==0){
            x=1;
            y=0;
            return a;
        }
        __int64 g=exGcd(b,a%b,x,y);
        __int64 temp=x;
        x=y;
        y=temp-(a/b)*y;
        return g;
    }
    int main()
    {
        __int64 a, b, c, x, y, gc;
        while(scanf("%I64d%I64d%I64d", &a, &b, &c) == 3)
        {
            gc = exGcd(a, b, x, y);
            if(c % gc)
            {
                printf("无解
    ");
                continue;
            }
            else
            printf("%I64d %I64d
    ", x*c/gc, y*c/gc);
        }
    }

     3 求逆元

    这个算法好久之前就想搞定,今天终于搞定了,好开心啊

    求a在mol b下的逆元, 即求满足a * x ≡ 1 (mod b)的x   //要求a和b互质

    套用扩展欧几里得模板,则苛求出来 满足 a * x + b * y = gcd(a, b)的x, 因为a,b互质,故gcd(a, b) = 1所求x即a在mod b情况下的逆元,

    输出大于0且最小的答案,所以 x = (x % b + b) % b;

    #include <iostream>
    using namespace std;
    void exgcd(int a, int b, int &x, int &y)
    {
        if(b==0)
        {
            x = 1;
            y = 0;
            return;
        }
        exgcd(b, a%b, x, y);
        int t = x;
        x = y;
        y = t - a/b*y;
    }
    
    
    int main()
    {
        int b,mod, x, y;
        while(cin>>b>>mod)
        {
            exgcd(b,mod, x, y);
            cout<<(x%mod+mod)%mod<<endl;
        }
        return 0;
    }
  • 相关阅读:
    解决Linux Ubuntu 突然出现死机无法进入系统的问题(sysrq magic key)
    [python笔记]文件处理
    [python笔记]pandas应用
    将Excel中列数转为列号
    Linq学习笔记
    install chrome for opensuse 12.1
    Word 文档拆分
    原型模式?java深克隆和浅克隆
    单例模式?学习懒汉式和饿汉式
    简单工厂模式?接口引用指向实例对象(面向接口)
  • 原文地址:https://www.cnblogs.com/rain-1/p/4780486.html
Copyright © 2020-2023  润新知