浅谈乘法逆元

一.定义

(及如何理解)

如果a*x≡1 (mod p),且gcd(a,p)=1(a与p互质),则称a关于模p的乘法逆元为x。(from Wikipedia)

a*x≡1 (mod p) 表示 a乘一个数x并模p等于1,即 a*x%p=1;看上去就是同余定理的一个简单等式。

而x 为 a 的逆元,记为x=a-1,所以我们也可以称 x 为 a 在mod b意义下的倒数,

什么意思呢? 可以理解为在x的倒数上加了个限定:

倒数定义为a*x=1,则x为a的倒数;

而逆元为:a*x%p=1;

用处:一般用于求 a/b (mod p) 的值(p 通常为质数),是解决模意义下分数数值的必要手段。

    (比如某道水题让你对结果%p,而计算过程中有除法运算。。)

二.求解

1.扩展欧几里得算法求解逆元

  我们知道,a*x≡1 (mod p) 就是 a*x%p=1 也就是 a*x+p*y=1  

  而扩展欧几里得算法就是用来求线性同余方程a?x≡c ( mod b ),只不过此时c=1;

  

#include<cstdio>
#include<cmath>
#define R register int
#define ll long long
using namespace std;
int n,p;

void ex_gcd(ll a,ll b,ll& x,ll& y)
{
    if(!b) x=1,y=0;
    else ex_gcd(b,a%b,y,x),y-=a/b*x;
}

int main()
{
    scanf("%d%d",&n,&p);
    for(R i=1;i<=n;i++)
    {
        ll x,y;
        ex_gcd(a,p,x,y);
        x=(x%p+p)%p;
        printf("%d\n",x);
    }
    return 0;
}

2.费马小定理和快速幂求解逆元

由费马小定理可知:ap-1≡1 (mod p)

所以a*ap-2≡1 (mod p)

即ap-2就是a在mod p意义下的逆元

#include<cstdio>
#include<iostream>
#include<cmath>
#define R register int
#define ll long long
using namespace std;

int n,p;

ll q_pow(ll x,ll ind,ll mod)
{
    x%=mod;
    ll a=1;
    for(;ind;ind>>=1,(x*=x)%=mod)
        if(ind&1) (a*=x)%=mod;
    return a;
}

int main()
{
    scanf("%d%d",&n,&p);
    for(R i=1;i<=n;i++) printf("%lld\n",q_pow(i,p-2,p));
    return 0;
}

3.O(n)的线性算法

  原题:P3811 【模板】乘法逆元 https://www.luogu.org/problemnew/show/P3811

  求 [1,n] 区间中每个数的逆元,其实这是一种递推。。。

  我们设 inv[i] 表示i的逆元,设 p=k*i+r (1<r<i<p) 可得:k*i+r≡0 (mod p)  (显然)

  则左右同乘 r-1 * i-1 :k*r-1+i-1≡0 (mod p)

  所以:i-1≡ -k*r-1 (mod p);

  易知:r-1=inv[p%i],k=p/i

  所以:i-1 = p/i * inv[p%i]

  而由逆元定义可知:inv[1]=1 (mod p),你就可以开始递推了。

  

#include<cstdio>
#include<iostream>
#define R register int
using namespace std;
int n,p;
int inv[3000010];

int main()
{
    scanf("%d%d",&n,&p);
    inv[1]=1;printf("1\n");
    if(p>=2) for(R i=2;i<=n;i++) inv[i]=(long long)(p-p/i)*inv[p%i]%p,printf("%d\n",inv[i]);//话说记得用long long寄存,要不就死了。。。
    return 0;
}

4.阶乘逆元

。。。还未学会。。。安利一发zjp_shadow大佬的blog:https://www.cnblogs.com/zjp-shadow/p/7773566.html (写得太好了)

原文地址:https://www.cnblogs.com/Jackpei/p/10358563.html

时间: 2024-10-16 10:26:14

浅谈乘法逆元的相关文章

浅谈欧拉定理及乘法逆元

浅谈欧拉定理及乘法逆元 本篇随笔简单讲解一下信息学奥林匹克竞赛数论部分欧拉定理及乘法逆元这一知识点.介绍的内容大致分为这么几个部分:"同余的基本概念.费马小定理.欧拉定理及其推论.乘法逆元". 同余的基本概念 同余的概念啊非常简单啦:如果两个整数\(a,b\)除以一个数\(m\)的余数相等的话,那么就叫做\(a,b\)在模\(m\)的意义上同余. 记作: \[ a\equiv b\,\,\,(mod\,\,m) \] 那么根据同余的这个定义,我们很容易能推导出一个性质:如果两个数\(a

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

原文链接(更好的阅读体验) 参考文章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{

浅谈算法和数据结构

: 一 栈和队列 http://www.cnblogs.com/yangecnu/p/Introduction-Stack-and-Queue.html 最近晚上在家里看Algorithems,4th Edition,我买的英文版,觉得这本书写的比较浅显易懂,而且“图码并茂”,趁着这次机会打算好好学习做做笔记,这样也会印象深刻,这也是写这一系列文章的原因.另外普林斯顿大学在Coursera 上也有这本书同步的公开课,还有另外一门算法分析课,这门课程的作者也是这本书的作者,两门课都挺不错的. 计算

浅谈C# 多态的魅力(虚方法,抽象,接口实现)

浅谈C# 多态的魅力(虚方法,抽象,接口实现) 分类:             asp.net             C#              2014-02-08 11:29     786人阅读     评论(0)     收藏     举报 浅谈C# 多态的魅力(虚方法,抽象,接口实现) 前言:我们都知道面向对象的三大特性:封装,继承,多态.封装和继承对于初学者而言比较好理解,但要理解多态,尤其是深入理解,初学者往往存在有很多困惑,为什么这样就可以?有时候感觉很不可思议,由此,面向

Http协议中Get和Post的浅谈

起名困难户,每次写文章最愁的就是不知道该如何起个稍具内涵的名字,如果这篇文章我只是写写Get和Post的区别,我可以起个名字“Get和Post的那点事”,如果打算阐述一下Http协议原理性内容,那该叫“Http中你不知道的那些事”,两者都不是我想要的,前者太过浅薄,后者太过深奥,已超出本人的能力范围,于是我只能写点Http,Get,Post和个稀泥大家就将就着看一下,开头很多废话的毛病我发现我是越来越难改了,进入正题吧~ Http HTTP(Hypertext transfer protocol

浅谈尾递归

浅谈尾递归 2013-02-10 14:12:57 在<数据结构与算法分析:C描述>(Data Structures and Algorithm Analysis In C)的第三章中,以打印链表为例,提到了尾递归(tail recursion)并指出了尾递归是使用递归极其不当的例子,它指出虽然编译器会对尾递归自动优化,但即便如此最好还是不要去写尾递归.而我在<算法精解:C语言描述>(Mastering Algorithms with C)中也看到书中提到编译器会对尾递归进行优化,

Linux的文本处理工具浅谈-awk sed grep

Linux的文本处理工具浅谈 awk   老大 [功能说明] 用于文本处理的语言(取行,过滤),支持正则 NR代表行数,$n取某一列,$NF最后一列 NR==20,NR==30 从20行到30行 FS竖着切,列的分隔符 RS横着切,行的分隔符 [语法格式] awk [–F] [“[分隔符]”] [’{print$1,$NF}’] [目标文件] awk 'BEGIN{FS="[列分隔符]+";RS="[行分隔符]+";print "-GEGIN-"

浅谈操作系统与内存

浅谈操作系统与内存 对于计算机的发明,相信大家都有耳闻那个占地面积按平米算的第一台计算机.在那个时候,CPU的资源是极其珍贵的,随着这些年突飞猛进的发展,一片指甲盖大小的民用级CPU一秒钟能执行的指令数可以达到上亿级别. 随着计算能力的增长,芯片外围的硬件和配套的软件也是一路高歌,发生了天翻地覆的变化,今天我们简单回顾历史,来看一看操作系统和内存机制的演变,不仅要了解它们是怎样,同时也看看它们为什么会是这样. CPU的运行 一说到CPU(Center processing unit),大家都觉得

.net中对象序列化技术浅谈

.net中对象序列化技术浅谈 2009-03-11 阅读2756评论2 序列化是将对象状态转换为可保持或传输的格式的过程.与序列化相对的是反序列化,它将流转换为对象.这两个过程结合起来,可以轻松地存储和传输数 据.例如,可以序列化一个对象,然后使用 HTTP 通过 Internet 在客户端和服务器之间传输该对象.反之,反序列化根据流重新构造对象.此外还可以将对象序列化后保存到本地,再次运行的时候可以从本地文件 中“恢复”对象到序列化之前的状态.在.net中有提供了几种序列化的方式:二进制序列化