【Algorithm】扩展欧几里得算法

裴属定理

若 a,b 是整数,且 gcd(a, b) = d,那么对于任意的 x,y,a * x + b * y 一定是 d 的倍数,特别地,一定存在整数 x,y 使得 a * x + b* y = d。


扩展欧几里得算法

在这里插入图片描述


// 求x, y,使得ax + by = gcd(a, b)
int exgcd(int a, int b, int &x, int &y)
{
    if (!b)
    {
        x = 1; y = 0;
        return a;
    }
    int d = exgcd(b, a % b, y, x);
    y -= (a/b) * x;
    return d;
}

线性同余方程

在这里插入图片描述

因为 a∗x ≡ b(mod m) 等价于 a∗x−b 是 m 的倍数,因此线性同余方程等价为a∗x+m∗y = b
根据裴蜀定理,上述等式有解当且仅当 gcd(a,m) | b
因此先用扩展欧几里得算法求出一组整数 x 0 x_0 x0,y_0, 使得 a∗ x 0 x_0 x0+m∗ y 0 y_0 y0 = gcd(a, m)。 然后 x = x 0 x_0 x0∗b / gcd(a, m) % m 即是所求。

#include <iostream>
#include <algorithm>

using namespace std;

typedef long long LL;

int exgcd(int a, int b, int &x, int &y)
{
    if (!b)
    {
        x = 1, y = 0;
        return a;
    }
    int d = exgcd(b, a % b, y, x);
    y -= a / b * x;
    return d;
}

int main()
{
    int n;
    scanf("%d", &n);
    while (n -- )
    {
        int a, b, m;
        scanf("%d%d%d", &a, &b, &m);

        int x, y;
        int d = exgcd(a, m, x, y);
        if (b % d) puts("impossible");
        else printf("%d\n", (LL)b / d * x % m);
    }

    return 0;
}
好的,让我为您解释一下**扩展欧几里得算法**及其在C语言中的实现。 ### 欧几里得算法简介 首先我们回顾一下基本的 **欧几里得算法** (Euclidean Algorithm),它用于求解两个整数的最大公约数(GCD)。其核心思想在于: ``` gcd(a,b) = gcd(b,a mod b) ``` 当b等于0时,则最大公因数即为a本身。这是一个非常高效的递归过程,并且时间复杂度接近对数值级别的增长速度O(log(min(a,b)))。 ### 扩展欧几里得算法介绍 而所谓的“**扩展版”**, 则是在原有基础上进一步发展出的一种计算方法——不仅可以找到两数之间的最大公约数g=gcd(a,b), 同时还能确定一对系数x,y使得 ax + by = g 成立. 这对我们解决一些线性同余方程、乘法逆元等问题特别有用. #### 算法步骤: 假设 a>b , 那么对于任意非负整数 k 我们都有: \[ax+by= \text{gcd}(a,b)=\text{gcd}(b,r)\] 其中 r=a%b; 因此如果已经知道了如何表示 gcd(b, r): \[bx_1+ry_1=\text{gcd}(b,r);\] 那么就可以回溯地表达原问题的答案了: 由于r=a-b*k;则有 \[ax+(b-k*a)y=b(x+y)-k*ay;\] 通过这种不断替换的方式最终可以得到满足条件的一组 x 和 y 的值. 下面是该算法的一个简单的 C 语言示例程序: ```c #include <stdio.h> // 定义一个函数来进行拓展欧几里德运算并返回三个结果作为数组元素 void extended_gcd(int a, int b, int *result_x, int *result_y, int *result_gcd){ if (!b){ // 当 b==0 时停止迭代 *result_x = 1; *result_y = 0; *result_gcd = a; } else { extended_gcd(b, a % b, result_x, result_y, result_gcd); // 计算新的X和Y int temp=*result_x - ((a / b)*(*result_y)); *result_x = *result_y ; *result_y=temp; } } int main(){ int a = 60; int b = 48; int x, y,gcd_value ; printf("Finding the GCD of %d and %d\n", a, b); // 调用延申版本的euclid algorithm获取结果 extended_gcd(a,b,&x,&y,&gcd_value); printf("The GCD is : %d\nAnd coefficients are (%d,%d)",gcd_value,x,y); } ``` 这段代码实现了上述描述的过程,并打印出了给定数字组合下的最大公因子以及相应的贝祖等式系数\(x\)及\(y\). 希望这个例子能够帮助您更好地理解这项技术!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值