乘法逆元的四种求法(拓展欧几里得、费马小定理、递归、递推)

前言

逆元:如果 a ∗ x ≡ 1 ( m o d   p ) a*x\equiv1(mod\ p) ax1(mod p),且a与p互质,则称x是a关于p的逆元。
对于这个概念和倒数有本质的区别,因为除法不能将mod数化进去。引用一个例子:

(a +  b) % p = (a%p +  b%p) %p  (对)

(a  -  b) % p = (a%p  -  b%p) %p  (对)

(a  *  b) % p = (a%p *  b%p) %p  (对)

(a  /  b) % p = (a%p  /  b%p) %p  (错)

为什么除法错的?
证明是对的难,证明错的只要举一个反例
(100/50)%20 = 2 ≠ (100%20) / (50%20) %20 = 0

对于一些题目,我们必须在中间过程中进行求余,否则数字太大,电脑存不下,那如果这个算式中出现除法,我们是不是对这个算式就无法计算了呢?

答案当然是 NO (>o<)
这时就需要逆元了

我们知道:
如果
ax = 1
那么x是a的倒数,x = 1/a
但是a如果不是1,那么x就是小数
那数论中,大部分情况都有求余,所以现在问题变了
a
x = 1 (mod p)
那么x一定等于1/a吗?

不一定
所以这时候,我们就把x看成a的倒数,只不过加了一个求余条件,所以x叫做 a关于p的逆元
比如2 * 3 % 5 = 1,那么3就是2关于5的逆元,或者说2和3关于5互为逆元
这里3的效果是不是跟1/2的效果一样,所以才叫数论倒数

a的逆元,我们用inv(a)来表示

那么(a / b) % p = (a * inv(b) ) % p = (a % p * inv(b) % p) % p
这样就把除法,完全转换为乘法了。

以上的例子摘自这篇博客,强推,浅显易懂!


对于法三用到如下公式变形:

证明:
设x = p % a,y = p / a
于是有 x + y * a = p
(x + y * a) % p = 0
移项得 x % p = (-y) * a % p
x * inv(a) % p = (-y) % p
inv(a) = (p - y) * inv(x) % p
于是 inv(a) = (p - p / a) * inv(p % a) % p

法四就是法三的记忆化版或者说是递推版

Code

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;

//拓展欧几里得
LL exgcd(LL A, LL B, LL &x, LL &y) {
   
  if (B == 0) {
   
    x = 1;
    y = 0;
    return A;
  }
  LL gcdnum = exgcd(B, A % B, x, y);
  LL tmp = y;
  y = x - A/B*y; //算上来的x,y计算出新的x,y
  x = tmp;
  return gcdnum;
}

//中速乘  : 对于长整型的快速乘要利用到80为的long double的特性O(1)  本算法复杂度O(logN)
LL qmul(LL a, LL b, LL mod) {
   
  LL ans = 0;
  a %= mod;
  while (b) {
   
    if (b&1) {
   
      ans = (ans + a) % mod;
    }
    a = (a << 1) % mod;
    b >>= 1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小胡同的诗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值