浅谈模质数意义下的乘法逆元

原文链接(更好的阅读体验)

参考文章www.luogu.org/blog/zyxxs/post-xiao-yi-jiang-tan-qian-tan-sheng-fa-ni-yuan

什么是乘法逆元

若整数\(b,m\)互质,并且\(b|a\),若存在一个整数\(x\),使得\(a / b \equiv a \ast x (mod \text{ } m)\),称\(x\)为 \(b\)的模\(m\)乘法逆元

乘法逆元的用处

有时候,我们需要求\(a/b \text{ } mod \text{ } p\),用朴素的方法,我们只能在\(a\)上不断加\(p\),直到它能被 bb 整除为止,当\(a,b,p\)都很大的时候,自然是凉凉了。这时,我们就可以用逆元方便的求解了。

乘法逆元的求法

进入到了本文最关键的部分,如何求乘法逆元?

费马小定理

费马小定理:当\(p\)是质数的时候,$a^{p-1} \equiv 1 (mod \text{ } p) $

那么将\(a^{p-1}\)拆开来,就得到了\(a \ast a^{p-2} \equiv (mod \text{ } p)\)

所以,\(a^{p-2}\)就是\(a\)模\(p\)意义下的乘法逆元。

缺点:用快速幂计算,当\(p\)比较大的时候,速度比较慢。

代码:

#include <algorithm>
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;

ll n, p;

ll ksm(ll a, ll b)
{
    ll ans = 1;
    for (; b; b >>= 1) {
        if (b & 1)
            ans = ans * a % p;
        a = a * a % p;
    }
    return ans;
}

int main()
{
    freopen("a.in", "r", stdin);
    freopen("a.out", "w", stdout);
    cin >> n >> p;
    for (int i = 1; i <= n; ++i) {
        printf("%lld\n", ksm(i, p - 2));
    }
    return 0;
}

扩展欧几里得算法

求\(a \ast x \equiv 1 (mod \text{ } m)\)的解\(inv(x)\),等价于求解\(a \ast x + b \ast y =1\)。用扩展欧几里得算法求出一组特解\(x_0, y_0\),则\(x_0\)是原方程的一个解,而方程的通解则为所有模\(m\)与\(x_0\)同余的整数,通过取模操作把解的范围移动到\(1~p\)之间即可。

代码:

#include <algorithm>
#include <cmath>
#include <iostream>
using namespace std;
typedef long long ll;

ll n, p;

void exgcd(ll a, ll b, ll& x, ll& y)
{
    if (b == 0) {
        x = 1, y = 0;
        return;
    }
    exgcd(b, a % b, x, y);
    ll z = x;
    x = y, y = z - y * (a / b);
    return;
}

int main()
{
    cin >> n >> p;
    for (int i = 1; i <= n; ++i) {
        ll x, y;
        exgcd(i, p, x, y);
        x = (x % p + p) % p;
        cout << x << endl;
    }
    return 0;
}

线性递推(可以求多个)

这是一个神奇的过程……

假设我们现在要求\(k\)的乘法逆元,

令 \(a \ast k + b = p\)

\[b \ast inv(b) \equiv 1 (mod \text{ } p)\]

把\(b=p-a\ast k\)代入,可以得到

\[(p-ak)\ast inv(b) \equiv 1 (mod \text{ } p)\]

那么

\[p \ast inv(b) - a \ast k \ast inv(b) \equiv 1 (mod \text{ } p)\]

在\((mod \text{ } p)\)的意义下,\(p \equiv 0 (mod \text{ } p)\),所以\(p \ast inv(b)\)可以直接去掉

\[-a \ast k \ast inv(b) \equiv 1 (mod \text{ } p)\]

观察\(a \ast k + b = p\)可以发现,\(a=\lfloor p/k \rfloor\),\(b=p \mod k\)

\[-(p/k) \ast inv(p \text{ } mod \text{ } k) \ast k \equiv 1 (mod \text{ } p)\]

\[-(p/k) \ast inv(p \text{ } mod \text{ } k) \equiv inv(k) (mod \text{ } p)\]

这样,我们就得了递推式,在实际的代码实现中得加上 \(p\) 来去掉负号,也就是

\[(p-p/k) \ast inv(p \text{ } mod \text{ } k) \equiv inv(k) (mod \text{ } p)\]

代码:

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <iostream>
using namespace std;
typedef long long ll;
ll n, p, inv[maxn];

int main()
{
    freopen("a.in", "r", stdin);
    freopen("a.out", "w", stdout);
    cin >> n >> p;

    inv[1] = 1;
    for (int i = 2; i <= n; ++i)
        inv[i] = (ll)(p - p / i) * inv[p % i] % p;
    for (int i = 1; i <= n; ++i)
        printf("%lld\n", inv[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/kkkstra/p/11331030.html

时间: 2024-08-04 13:56:25

浅谈模质数意义下的乘法逆元的相关文章

浅谈线程池(下):相关试验及注意事项

三个月,整整三个月了,我忽然发现我还有三个月前的一个小系列的文章没有结束,我还欠一个试验!线程池是.NET中的重要组件,几乎所有的异步功能依赖于线程池.之前我们讨论了线程池的作用.独立线程池的存在意义,以及对CLR线程池和IO线程池进行了一定说明.不过这些说明可能有些"抽象",于是我们还是要通过试验来"验证"这些说明.此外,我认为针对某个"猜想"来设计一些试验进行验证是非常重要的能力,如果您这方面的能力略有不足的话,还是尽量加以锻炼并提高吧. C

【Vue】浅谈Vue不同场景下组件间的数据交流

浅谈Vue不同场景下组件间的数据“交流” Vue的官方文档可以说是很详细了.在我看来,它和react等其他框架文档一样,讲述的方式的更多的是“方法论”,而不是“场景论”,这也就导致了:我们在阅读完文档许多遍后,写起代码还是不免感到有许多困惑,因为我们不知道其中一些知识点的运用场景.这就是我写这篇文章的目的,探讨不同场景下组件间的数据“交流”的Vue实现 父子组件间的数据交流 父子组件间的数据交流可分为两种: 1.父组件传递数据给子组件 2.子组件传递数据给父组件 父组件传递数据给子组件——pro

浅谈在ES5环境下实现const

最近看到一个面试题--用ES5实现const.作为JS初学者的笔者知道在ES6中有const命令,可以用来声明常量,一旦声明,常量的值就不可改变.例如: 1234567891011 const Pi = 3.1415;Pi Pi = 3;// TypeError: Assignment to constant variable. const foo = {};// 为 foo 添加一个属性,可以成功foo.prop = 123;foo.prop // 123// 将 foo 指向另一个对象,就会

不超过 $10^{18}$ 的非负整数在模意义下的乘法

约定:在博主的校内 OJ 上, long double  类型支持阶码 $15$ 位.有效值 $63$ 位(即科学记数法保留 $64$ 位有效数字).以下讨论以此为前提. 设非负整数 $a, b, p$ 满足 $a, b<p<2^{63},\ p \ne 0,$ 求 $ab \bmod p.$ $$ab \bmod p=ab-p\left\lfloor {ab \over p} \right\rfloor$$ 我们知道 $\left\lfloor {ab \over p} \right\rfl

浅谈优化程序性能(下)

前言 在上一篇随笔中,我们谈到最小化一个计算中的操作数量不一定会提高它的性能.现在,就让我们来解开为什么会出现这种情况的原因吧. 处理器体系结构 在计算机的处理器中,处理一条指令包括很多操作,可以分为取指(fetch).译码(decode).执行(execute).访存(memory).写回(write back)和更新程序计数器(PC update)等几个阶段.这些阶段可以在流水线上同时进行,如下图所示: 上图中,F.D.E.M 和 W 分别代表上述五个阶段.当然,现代的处理器比这个示例要复杂

浅谈Nginx(二)—http下server配置

此文介绍Nginx下的http模块,着重介绍http模块下的server服务 --------依据"马哥教育"主讲人马永亮导师的上课笔记整理------- 目录  一. http相关的基本配置:     1) listen                2) server_name           3) tcp_nodelay     4) sendfile      二. 定义路径相关的配置:     1)root path     2)location     3)alias 

浅谈解耦的意义---我们一直追求解耦,却不知道她哪里好

谈到解耦,就要提到设计模式,设计模式来源于分析模式,设计模式是分析模式的具体现话.              举个例子,我们购买一个大件,像冰箱. 从客观的角度分析,这种东西不是我们直接拿走的,那么我们简化这个流程就是:你选择冰箱,给钱,然后营业员给你生成订单,送货人发货.如果说我们把选择冰箱,下单付款,送货期间作为粉色的时间,然后,我中间牵扯到的营业员,送货人,客户这类的参与者作为绿色,最后中间的权限例如业务员收钱的时候,从数据考虑,他是操作财务表的权限,订单是操作订单表的权限,这部分权限作为

浅谈经济新常态下农业现代化的四个方面

摘要:本文从四个方面阐述了我国经济新常态下农业现代化,即是农业现代化的内容也是农业的发展方向.我们要在认清农业现代化的内容和意义上,坚定积极的推进农业的现代化之路. 关键词:新常态,科技,农业现代化,市场 中国经济目前处在一个三期叠加阶段的新常态,即增长速度进入换档期,结构调整面临阵痛期,前期刺激政策消化期.我国由改革开放三十年来均10%的经济增速,把我国经济提升到世界第二大经济体的地位.从各种生产要素的结构分析来看,这种增长速度的下降是经济发展的阶段性现象.这一时期也要加快转变经济发展方式,优

浅谈测试的意义和方法

背景: 本人曾干过1年多测试系统工程师,在此期间思考了测试的意义和方法,故记下来 关于测试工作的设想工作性质的认识, 工作职责是QC, 工作意义: 对于产品质量提升的意义: 1.1质量:在研发后,由测试人员进行独立的从模块到整机的测试,保证产品质量.和行业领先的竞争对手做比较,达到甚至超过他们的产品质量.通过模块测试保证,模块测试将扩展到IC芯片信号测试 1.2性能:首先满足设计(芯片和整机方案)的性能指标,其次与行业领先的竞争对手进行性能比较,为最终的性能提升提供规范准确的报告. 2工作内容