扩展欧几里德算法求模逆元
时间: 2023-07-19 21:04:04 浏览: 154
扩展欧几里德算法可以用来求解两个数的最大公约数,同时也可以用来求解模逆元。模逆元是指在模意义下,一个数的乘法逆元,即如果a与m互质,那么存在b, 使得a*b mod m = 1。
假设我们要求解a在模m意义下的乘法逆元,我们可以使用扩展欧几里德算法来解决这个问题。
首先,我们需要运用普通的欧几里德算法求出a和m的最大公约数d,同时记录下每一步的余数和商,直到余数为0为止。例如:
```
a = 42, m = 17
42 = 17 * 2 + 8
17 = 8 * 2 + 1
8 = 1 * 8 + 0
```
因此,最大公约数d为1。
接下来,我们需要利用逆向思维,从最后一步开始,倒推出b和c的值。因为在求解最大公约数的过程中,我们得到了以下等式:
```
1 = 17 - 8 * 2
8 = 42 - 17 * 2
```
将8代入上一式子中,得到:
```
1 = 17 - (42 - 17 * 2) * 2
```
化简后得到:
```
1 = 3 * 17 - 2 * 42
```
因此,我们得到了a在模m意义下的乘法逆元b为-2,但是这个结果是负数,所以我们需要将其转化为正数。根据模运算的性质,b = b mod m + m,因此:
```
b = -2 mod 17 + 17 = 15
```
因此,42在模17意义下的乘法逆元为15。
相关问题
C语言扩展欧几里德算法求模逆元
扩展欧几里德算法可以用来求解模线性方程,其中就包括求解模逆元的问题。假设我们需要求解 a 在模 m 意义下的逆元 x,即 ax ≡ 1 (mod m),那么就可以使用扩展欧几里德算法来求解。
具体步骤如下:
1. 用欧几里得算法求出 a 和 m 的最大公约数 gcd(a, m),如果 gcd(a, m) 不等于1,则 a 在模 m 意义下没有逆元。
2. 使用扩展欧几里德算法求出 ax + my = gcd(a, m) 的一组整数解 (x, y)。
3. 如果 gcd(a, m) 等于1,则 ax ≡ 1 (mod m) 的一个解就是 x,但是 x 可能为负数或者大于等于 m,因此需要对 x 做一些调整,使得 x 在 [0, m) 范围内。
以下是使用 C 语言实现的代码:
```c
#include <stdio.h>
// 扩展欧几里德算法求解 ax + my = gcd(a, m) 的一组整数解 (x, y)
int exgcd(int a, int b, int *x, int *y) {
if (b == 0) {
*x = 1;
*y = 0;
return a;
}
int d = exgcd(b, a % b, y, x);
*y -= a / b * (*x);
return d;
}
// 求解模逆元 ax ≡ 1 (mod m)
int mod_inv(int a, int m) {
int x, y;
int d = exgcd(a, m, &x, &y);
if (d != 1) {
printf("%d 在模 %d 意义下没有逆元\n", a, m);
return -1;
}
return (x % m + m) % m;
}
int main() {
int a = 3, m = 11;
int x = mod_inv(a, m);
if (x != -1) {
printf("%d 在模 %d 意义下的逆元是 %d\n", a, m, x);
}
return 0;
}
```
上面的代码中,exgcd 函数用于求解 ax + my = gcd(a, m) 的一组整数解 (x, y)。如果 gcd(a, m) 不等于1,则表示 a 在模 m 意义下没有逆元,此时 mod_inv 函数返回 -1。否则,mod_inv 函数返回 x 的值,表示 a 在模 m 意义下的逆元。注意,最后需要对 x 做一些调整,使得 x 在 [0, m) 范围内。
用c语言实现扩展欧几里德算法求模逆元
扩展欧几里德算法求模逆元可以用来解决一类问题,即对于给定的整数a和模数m,求出一个整数x使得ax ≡ 1 (mod m)。下面是用C语言实现扩展欧几里德算法求模逆元的代码:
```c
#include <stdio.h>
// 求最大公约数
int gcd(int a, int b, int *x, int *y)
{
if (b == 0) {
*x = 1;
*y = 0;
return a;
}
int r = gcd(b, a % b, x, y);
int t = *x;
*x = *y;
*y = t - a / b * *y;
return r;
}
// 求模逆元
int mod_inv(int a, int m)
{
int x, y;
int g = gcd(a, m, &x, &y);
if (g != 1) {
printf("No solution!\n");
return -1;
} else {
return (x % m + m) % m;
}
}
// 测试
int main()
{
int a = 5, m = 7;
int inv = mod_inv(a, m);
if (inv >= 0) {
printf("%d 的模 %d 逆元是 %d\n", a, m, inv);
}
return 0;
}
```
在上面的代码中,我们首先定义了一个函数`gcd`,用来求解最大公约数。这个函数的输入参数包括两个整数a和b,以及两个指向整数的指针x和y。函数返回值是a和b的最大公约数。在函数中,我们采用了递归的方式来求解最大公约数,并利用指针x和y保存了扩展欧几里德算法中每次迭代后的结果。
接下来,我们定义了一个函数`mod_inv`,用来求解模逆元。这个函数的输入参数包括两个整数a和m,表示要求解的模逆元是a关于模数m的逆元。函数返回值是a关于模数m的逆元,如果不存在,则返回-1。在函数中,我们首先调用了函数`gcd`来求解a和m的最大公约数,并利用指针x和y保存了扩展欧几里德算法中每次迭代后的结果。如果a和m的最大公约数不为1,则说明不存在模逆元,函数返回-1。否则,我们利用扩展欧几里德算法的结果来计算模逆元,并返回结果。
最后,在主函数中,我们定义了两个整数a和m,并调用函数`mod_inv`来求解a关于模数m的逆元。如果求解成功,则输出结果,否则输出错误信息。
阅读全文