拓展欧几里得求逆元
为什么要学逆元
我也不知道,比如(a/b)%p要是里面是个分数就g了
逆元说白了就是倒数
逆元的概念
在 (a / b) % p 中,我们可以使用逆元的概念将其表示为 (a * b') % p,其中 b' 是 b 在模 p 意义下的逆元。注意是是b在%p的逆元是b‘
心得
ax ≡ 1 (mod b)
ax+by=1 这个已经是知道的
我们要求的是x 欧几里得可以拿来解二元一次的 因为ax+by=gcd(a,b)这是一定的
然后就是
(a * x) % m = 1 我后面会提到一个问题
在下面的代码中 return a=1,就是两个互质的最大公约数 为1 也只有互质了 我们才可以求逆元 这是一定的
在 int d = exgcd(b, a % b, y, x); 这一行,递归返回的结果 d 被记录就是1,x 和 y 的值也被更新为递归调用中传递的 y 和 x。
加深了我对&这个的理解
然后就是((LL)x % m + m) % m ,我们要的逆元是正整数,真的不考虑负数
注意负数%也是负数 所以加m下面第一行考虑的x为正数 不过一般谁考虑x是负数 当然了除非题目说了,比如 2* (-3) ≡ 1 (mod -5)。
逆元就是-3
(a/b)%p=(a*x)%p
(LL)x % m:取 x 对 m 的余数。这确保结果在 [0, m-1] 的范围内。
+ m:为了确保结果是非负数,加上 m。
% m:再次取模,确保结果在 [0, m-1] 的范围内,同时保留正整数。
回答上面那个问题 我当时想如果x是-2 m=5输出不成3吗 (a * x) % m = 1 要满足这个的不是乱来的。
那只是我的月意想
下图介绍了原理和证明,实际中exgcd这个函数会一直执行到b==0为止,具体有多少次,很多吧,
exgcd(b, a % b, y, x);
(int a, int b, int &x, int &y)
注意这个 每一次y直接赋值给了x,就简化了。
然后就是计算了 根图片上说的一样。
其实是gcd(a,b)=gcd(b,a%b)=gcd((a%b,b%(a%b))).....

下面是用于求解
ax+by=gcd(a,b)的解的代码 包含了逆元 逆元就是后面直接为1了
#include<iostream>
using namespace std;
int x, y;
void exgcd(int a, int b, int &x, int &y)
{ if(b == 0){
x = 1, y = 0;
return ;
}
exgcd(b, a % b, y, x);
y = y - a / b * x;
}
int main(){
int n, a, b;
cin >> n;
while(n -- ){
cin >> a >> b; exgcd(a, b, x, y);
cout << x << ' ' << y << endl;
}
}
没什么好说的 短短的代码却写了这么久 理解这么久累死我了

浙公网安备 33010602011771号