线性求逆元模板_算法学习笔记(9):逆元

本文详细介绍了数论中求逆元的概念及其在模运算中的应用。通过拓展欧几里得、费马小定理和线性递推三种方法解决模意义下的除法问题,特别是在解决洛谷P3811模板题时,线性递推方法的优势得以体现,适用于大量乘法逆元的计算,降低了时间复杂度。
摘要由CSDN通过智能技术生成

782512fb8af2030e00b3aa9fc63eea89.png

https://zhuanlan.zhihu.com/p/105467597在数论中,如果

,我们就说
在模
意义下互为乘法逆元,记作

逆元有什么用呢?我们常常遇到一些题目要求结果对一个大质数

取模,这是因为答案很大,出题人为了不麻烦大家写高精,就采取这样的方法。
加减法乘法对取模运算都是 封闭的,所以你可以处处取模来避免溢出。

a7aa930fd756cb726e4536d71ac13c8b.png
一次取模和步步取模的结果是一样的

但遇到除法时,就麻烦了:

ad5626b6898418c37dcac0f092815b4f.png
出现了2/3这种无法处理的情况

为了解决模意义下的除法问题,我们引入了逆元。

其实可以看做模
意义下的
,那么在模
意义下,
就可以变形为

实际上在模

意义下
,所以上面的式子可以这样计算:

89134ebf56aa0b5d3b003c45082734c5.png

这里介绍三种计算逆元的方法:拓展欧几里得费马小定理线性递推


拓展欧几里得

这种方法上一节已经介绍了,那道“同余方程”其实就是在求逆元。实际上,这就是最常用的求逆元的方法。代码如下:

ll exgcd(ll a, ll b, ll &x, ll &y)// 拓欧
{
    if (b == 0)
    {
        x = 1;
        y = 0;
        return a;
    }
    ll d = exgcd(b, a % b, y, x);
    y -= (a / b) * x;
    return d;
}
ll inv(ll a, ll p)
{
    ll x, y;
    if (exgcd(a, p, x, y) != 1) // 无解的情形
        return -1;
    return (x % p + p) % p;
}

费马小定理

费马小定理是数论里的重要定理,叙述如下:

是质数,且
,则有

从逆元的定义推导,可得

,于是有

于是对

算一下
快速幂就好了。注意这个方法只对
是质数的情形有效。
inline ll qpow(ll a, ll n, ll p)// 快速幂
{
    ll ans = 1;
    while (n)
    {
        if (n & 1)
            ans = ans % p * a % p;
        a = a % p * a % p;
        n >>= 1;
    }
    return ans;
}
inline ll inv(ll a, ll p)
{
    return qpow(a, p - 2, p);
}

线性递推

以上两种方法都是常用的求逆元方法,但是,洛谷上的这道毒瘤模板题,必须要用特殊的方法:

洛谷P3811 【模板】乘法逆元

题目背景
这是一道模板题 题目描述
给定
中所有整数在模
意义下的乘法逆元。
输入格式
一行两个正整数
输出格式
输出
行,第
行表示
在模
下的乘法逆元。

因为这道题要求一系列的乘法逆元,而且数据范围是

,常规方法是行不通的。这里介绍逆元的
线性递推求法(需保证
是质数)。

, 即

在模

意义下,有

移项整理得

其实和拓展欧几里得还是有不少相似之处的。我们可以用记忆化搜索的方法,减少多次查询的时间复杂度(空间换时间)。(递推亦可,其实就这题而言递推更好)

// 多次对不同的p使用需要清空Inv数组
ll Inv[MAXN] = {0, 1};
inline ll mod(ll a, ll p)
{
    return (a % p + p) % p;
}
ll inv(ll a, ll p)
{
    if (Inv[a])
        return Inv[a];
    Inv[a] = mod(-p / a * inv(p % a, p), p);
    return Inv[a];
}

https://zhuanlan.zhihu.com/p/105467597​zhuanlan.zhihu.com
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值