建议大家可以先去看看这篇博文
(https://www.cnblogs.com/dupengcheng/p/5487362.html)
乘法逆元:ax≡1 (mod p) 这个等式用中文描述就是 a乘一个数x并模p等于1,即 a%p*x%p=res【并非指res等于1】,而是res%p=1;其中的x为满足范围还要对p求模

需知道的是:
若ax≡1 mod f, 则称a关于1模f的乘法逆元为x。也可表示为ax≡1(mod f)。
当a与f互素时,a关于模f的乘法逆元有解。如果不互素,则无解。如果f为素数,则从1到f-1的任意数都与f互素,即在1到f-1之间都恰好有一个关于模f的乘法逆元。【百度百科-乘法逆元】

什么是逆元,为什么要求逆元?

计蒜客某题所表述:

那么了解基本知识后,我们来求逆元:
求逆元分为两类:
1.a p 不互质时逆元无解
可用公式实现相同功能:

证明:

推荐题目:蓝桥杯小数第n位

2.a p 互质时:
逆元的求法主要有三种(按快慢排序):
第一:线性打表递推法(递推公式inv[i]=(p-p/i) * inv[p%i]%p)。
第二:扩展欧几里得算法。(详解)
第三:费马小定理(快速幂qpow(a,p-2,p))。-(最容易理解)

下面我们把每种求法的模板呈上:

例题引入:乘法逆元

Description

这是一道模板题。
给定正整数 n 与 p ,求 1∼n 中的所有数在模 p 意义下的乘法逆元。

Input

一行两个正整数 n 与 p

1 ≤ n ≤ 3×106 , n < p < 20000528

p 为质数。

Output

n 行,第 i 行一个正整数,表示 i 在模 p 意义下的乘法逆元
Sample Input

10 13

Sample Output

1
7
9
10
8
11
2
5
3
4

第一:线性打表递推法(递推公式inv[i]=(p-p/i)inv[p%i]%p)
时间对比:

参考于:(https://blog.csdn.net/xuechen_gemgirl/article/details/80332859)

#include<bits/stdc++.h>
using namespace std;
#define ll long long int
ll inv[20000530];
//记吧线性模板 递推公式挺简单的 (p-p/i)*inv[p%i]%p;
//数据量大的时候就明显可以看到比快速幂快了
int main(void)
{ll a,p;while(~scanf("%lld %lld",&a,&p)){memset(inv,0,sizeof(inv));inv[0]=inv[1]=1;for(int i=2;i<=a;i++){inv[i]=(p-p/i)*inv[p%i]%p;}for(int i=1;i<=a;i++)printf("%lld\n",inv[i]);}return 0;
}

第二:扩展欧几里得算法
时间复杂度:
为什么可以用扩展欧几里得求得逆元?

我们都知道模就是余数,比如12%5=12-5 * 2=2,18%4=18-4*4=2。(/是程序运算中的除)可知a%b=a-(a/b)b

那么ax≡1 (mod p)即ax-yp=1.把y写成+的形式就是ax+py=1,为方便理解下面我们把p写成b就是ax+by=1。就表示x是a的模b乘法逆元,y是b的模a乘法逆元。然后就可以用扩展欧几里得求了。
摘自上面链接(https://www.cnblogs.com/dupengcheng/p/5487362.html,推荐大家先看一遍)

很多人,包括我一直无法理解扩展欧几里得算法,在我看了好多博文后才大概了解。就拿我碰到的来说:
一扩展欧几里得可以求最大公约数。
二求ax+by=gcd(a,b)的解x,y。逆元就包括其中。
x是a的模b乘法逆元,y是b的模a乘法逆元(即gcd()=1时的x/y)

现在来讲一下扩展欧几里得到底怎么来的:
其实我觉得大家只要搞懂后面递归的x,y怎么求就几乎没问题的了。
原式:ax+by=gcd(a,b)
递归:bx+(a%b)y^=gcd(a,b) 【
x^和 y^就是上一步的x,y】
其中:a%b=a-(a/b)b
带入后:ay^+b ( x ^ - ( a/b ) y ^ )=gcd(a,b);
再与原式对比:ax+by=gcd(a,b)
得出:{
x=y^;
x^-(a/b ) y ^=y;
}

这就是递归过程中,x和y的由来
而当b=0时,有:(递归结束时){a=gcd(a,b),x=1,y=0}
a1+b0=a=gcd(a,b)
可得出一个特解a(最大公约数)

这样就可以得到每两个相邻状态的x和y的转化了,就可以在求gcd(a,b)的同时求对x,y求解

相信对于扩展欧几里得算法,大家会有疑问为什么b=0时x=1;y=0?
其实当达到递归基时,此时的a就是gcd(最大公约数),b=0,那么有ax+by=a。
x必须等于1,y可以取任何正整数

我还是有疑问上面说了“x是a的模b乘法逆元,y是b的模a乘法逆元”
大家都统一b=0时x=1;y=0;。既然y可以取任何正整数那么我就要换一个当b=0时:x=1;y=1;这个“x是a的模b乘法逆元,y是b的模a乘法逆元”结论还是成立的。

还有一点就是建议y取0,如果取其他数组,由于y增长较快,可能会有越界的问题。

#include<bits/stdc++.h>
using namespace std;
int exgcd(int a,int b,int &x,int &y)//扩展欧几里得算法
{if(b==0){x=1;y=0;return a;  //到达递归边界开始向上一层返回}int r=exgcd(b,a%b,x,y);int temp=y;    //把x y变成上一层的y=x-(a/b)*y;x=temp;return r;     //得到a b的最大公因数
}
//事实证明还是递推快 递推快但是耗空间
int main(void)
{int a,p;//p是mod数int x,y;while(~scanf("%d %d",&a,&p)){for(int i=1;i<=a;i++){exgcd(i,p,x,y);if(x>0)printf("%d\n",x);elseprintf("%d\n",x+p);//确保逆元x为正整数}}return 0;
}

第三:费马小定理(快速幂qpow(a,p-2,p))
时间复杂度对比:

为什么可以用费马小定理来求逆元呢?
(前提是a p 互质)
由费马小定理 ap-1≡1(mod p) , 变形得 a * ap-2≡1(mod p),答案已经很明显了:若a,p互质,因为a * ap-2≡1(mod p)且a*x≡1(mod p),则逆元x=ap-2(mod p),用快速幂可快速求之。
摘自上面链接(https://www.cnblogs.com/dupengcheng/p/5487362.html)

#include<bits/stdc++.h>
using namespace std;
#define ll long long int
ll qpow(ll a,ll b,ll p)
{ll ans=1;while(b){if(b%2==1){ans%=p;a%=p;ans=ans*a%p;    }a%=p;a=a*a%p;b=b>>1;}return ans%p;
}
int main(void)
{ll a,p;//p是质数while(~scanf("%lld %lld",&a,&p)){for(int i=1;i<=a;i++){printf("%lld\n",qpow(i,p-2,p));}}return 0;
}

明显在大量数据的时候递推打表快,平时普通问题用另外两个比较方便,但是由于本人数学知识薄弱不能给出证明【捂脸】
给个大佬讲解的链接:https://blog.csdn.net/guhaiteng/article/details/52123385

乘法逆元3种方法总结[最全]相关推荐

  1. Java实现九九乘法表(三种方法实现)

    Java实现九九乘法表(三种方法实现) 题目要求: /*输出以下九九乘法表 1 * 1 = 1 2 * 1 = 2 2 * 2 = 4 ......*/ 代码实现一(使用两层for循环--最常用): ...

  2. C语言中的输出99乘法表4种方法

    下面讲述4中正向反向,靠左靠右的输出方法: 首先,引入头文件 #define _CRT_SECURE_NO_WARNINGS 1//用于忽略scanf函数不安全警告 #include<stdio ...

  3. 大整数乘法的5种方法

    模拟小学乘法:最简单的乘法竖式手算的累加型: 分治乘法:最简单的是Karatsuba乘法,一般化以后有Toom-Cook乘法: 快速傅里叶变换FFT:(为了避免精度问题,可以改用快速数论变换FNTT) ...

  4. JavaScript实现九九乘法表四种方法(附代码)

    几行代码就能轻松学会 <!DOCTYPE html> <html lang="en"> <head><meta charset=" ...

  5. 九九乘法表 两种方法

    #九九乘法表 i=1 n=1 for i in range(1,10,1):for n in range(1,i+1):print("%d*%d=%d"%(i,n,i*n),end ...

  6. PHP生成随机数的几种方法(最全)

    原文链接:http://oldchen.iwulai.com/index.php/2019/01/16/php%E7%94%9F%E6%88%90%E9%9A%8F%E6%9C%BA%E6%95%B0 ...

  7. Linux查看文件大小的几种方法(超全)

    一.stat命令 stat指令:文件/文件系统的详细信息显示. stat命令主要用于显示文件或文件系统的详细信息,该命令的语法格式如下: -f 不显示文件本身的信息,显示文件所在文件系统的信息 -L ...

  8. 数据库备份的四种方法 软件功能需求分析

    数据库备份的四种方法: l 全备份:创建备份完成时数据库内存在的数据的副本. l 差异备份:只记录自上次数据库备份后发生更改的数据.差异数据库备份比数据库备份小,而且备份速度快,因此可以更经常地备份, ...

  9. 求乘法逆元的几种方法

    (数学渣,下面的文字可能有误,欢迎指教) 乘法逆元的定义貌似是基于群给出的,比较简单地理解,可以说是倒数的概念的推广.记a的关于模p的逆元为a^-1,则a^-1满足aa^-1≡ 1(mod p) 加减 ...

最新文章

  1. table列最小宽度 vue_vue中获取滚动table的可视页面宽度调整表头与列对齐(每列宽度不都相同)...
  2. POJ 1321 棋盘问题【DFS】
  3. Linux 网络编程(TCP)
  4. TensorFlow:将ckpt文件固化成pb文件
  5. 普通的年轻状态机,纯C语言
  6. 机器学习入门学习笔记:(2.3)对数几率回归推导
  7. mit oracle hd120,【出】MIT Oracle Matrix HD100 喇叭线 10呎
  8. VTK:绘图之SurfacePlot
  9. C语言-实现矩阵的转置-随机函数产生随机数并赋予数组中-190222
  10. pythontime库简单使用_Python time库基本使用方法分析
  11. vs2015 动态链接库问题
  12. API函数的调用过程
  13. 数据结构---哈希表的C语言实现
  14. 常见音频编码格式总结
  15. 安卓无线打印服务器,安卓 打印服务器
  16. 准备换工作 , 有备无患
  17. 自我介绍php一句话,面试自我介绍经典语句,经典一句话自我介绍
  18. 洛谷P3131 [USACO16JAN]Subsequences Summing to Sevens S
  19. vue-ant design示例大全——按钮本地css/js资源
  20. redis常用操作2, redis操作键值, redis安全设置

热门文章

  1. SSM毕设项目基于的NBA球队管理系统8x21a(java+VUE+Mybatis+Maven+Mysql)
  2. HCFT和HCFTstar在OTB数据集中测试的接口函数
  3. 软件项目管理 7.1.项目进度基本概念
  4. avada 修改head.php,php - 使用WordPress Avada子主题将主徽标链接到自定义URL而不是首页? - 堆栈内存溢出...
  5. android官方wifidemo,Android连接指定Wifi的Demo
  6. 阿里巴巴2008年创纪录狂招2000多销售人才
  7. 毕业设计--2020-1-13 DS3231秒出问题(秒读数全部是偶数的原因)
  8. 继内存条、固态硬盘后国产CPU再度发力,性能已媲美10代酷睿
  9. 【数字测图原理与方法】绪论与测量基本知识
  10. c语言编程排球队员站位问题,【排球课堂】一文看懂排球常识 解说总提的“卡轮”原来如此...