扩展欧几里得算法

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;
}
原文地址:https://www.cnblogs.com/rain-1/p/4780486.html