(数论)简单总结求逆元的几种方法

逆元(Inverse element),如a?b≡1(modp),那么a,b互为模p意义下的逆元,则p|(a/c-b*c)(即a/c与b*c同余)。

常用的求逆元方法有

1.费马小定理

  若p为素数,且gcd(a,p)=1,则a^(p-1)≡1(mod p),即a*a^(p-2)≡1(mod p),故a的逆元为a^p-2。

2.拓展欧几里德算法(递推再回溯)

  当gcd(A,B)|C时,可求二元一次方程Ax+By=C的整数通解。

3.逆元线性筛

  递推公式:inv[i]=inv[p % i] * (p - p / i) % p;

  (注意:p为质数!)

4.一般公式(条件b|a)【并没有求逆元,而是将等式化为了另一形式】

  a / b mod m=a mod (m * b) / b;

原文地址:https://www.cnblogs.com/Ekalos-blog/p/9672264.html

时间: 2024-08-08 02:21:09

(数论)简单总结求逆元的几种方法的相关文章

除法求模中求逆元的两种方法

今天下午还是有点闲的,不想刷题,不想补题,突然想起昨天的training 3里I题涉及到除法取模的问题,就来总结一下 首先对于模运算来说,是没有对于除法的取模的(即没有(a/b)%mod==a%mod/b%mod),但是在很多题目中都涉及到除法取模,所以就必须要了解或者掌握,对于除法取模以(a/b)%mod来说,我们首先需要得到b的逆元,根据逆元的定理 对于正整数和,如果有,那么把这个同余方程中的最小正整数解叫做模的逆元. 然后就是求逆元的两种方法. 第一种方法就是比较普遍的,也是挺基础的,就是

求乘法逆元的几种方法

(数学渣,下面的文字可能有误,欢迎指教)乘法逆元的定义貌似是基于群给出的,比较简单地理解,可以说是倒数的概念的推广.记a的关于模p的逆元为a^-1,则a^-1满足aa^-1≡ 1(mod p) 加减乘与模运算的顺序交换不会影响结果,但是除法不行.有的题目要求结果mod一个大质数,如果原本的结果中有除法,比如除以a,那就可以乘以a的逆元替代. 在mod p的运算中,a存在乘法逆元当且仅当a与p互质.一般题目给的是一个大质数,所以只要a不是p的倍数,就以求乘法逆元. 目前了解到的求法有三种:1.扩展

求逆元的四种算法(拓欧费马小线性推欧拉)

求逆元的四种算法 拓展欧几里得算法求逆元 上一篇博客中已经讲过拓展欧几里得算法,并且讲解了求逆元的原理.这里只列出代码 在要求逆元的数与p互质时使用 代码 //扩展欧几里得定理 int ex_gcd(int a,int b,int& x,int& y) { if(b==0) { x=1; y=0; return a; } int ans = ex_gcd(b,a%b,x,y); int tmp = x; x = y; y = tmp-a/b*y; return ans; } int cal

简单程序的编译链接三种方法(编译多个源文件,静态链接库、动态链接库)

一个程序简单的程序如下: 1 hello.h #ifndef HELLO_H#define HELLO_H void hello(const char *name); #endif 2 hello.c #include <stdio.h>#include <stdlib.h> void hello(const char *name){ printf("hello %s\n",name);} 3 main.c #include <stdio.h>#in

求平均数的四种方法

用c语言求平均数有四种方法,各有利弊.1.第一种是最常规的做法例 > int main() { int a = 10; int b = 5; c = (a + b) / 2; system("pause"); return 0; } 这种方法有缺陷,如果a和b足够大,以致于两数之和超出了intmax(整型所能代表的最大值),所以不建议使用这种方法.2.最常用的方法例 > int main() { int a = 10; int b = 5; c = a+(b-a)/2; s

SpringBoot中使用Spring Data Jpa 实现简单的动态查询的两种方法

首先谢谢大佬的简书文章:http://www.jianshu.com/p/45ad65690e33# 这篇文章中讲的是spring中使用spring data jpa,使用了xml配置文件.我现在使用的是spring boot ,没有了xml文件配置就方便多了.我同样尝试了两种方式,也都是简单的查询,需要更复杂的查询,还需要我研究研究.往下看,需要先配置springboot的开发环境,需要大致了解springboot,这里可以看下面两篇文章: springboot 项目新建 springboot

求 LCA 的三种方法

(YYL: LCA 有三种求法, 你们都知道么?) (众神犇: 这哪里来的傻叉...) 1. 树上倍增 对于求 LCA, 最朴素的方法是"让两个点一起往上爬, 直到相遇", "如果一开始不在同一深度, 先爬到同一深度". 树上倍增求 LCA 的方法同样基于这个道理, 只不过利用了倍增思想从而加速了"向上爬"的操作. 也就是说, 每次向上爬的高度不是 1, 而是 2 的幂. 我们用 $f(i, j)$ 表示从节点 $i$ 向上爬 $2^j$ 的高度

递归很耗内存+多项式求值的两种方法+c语言计时方法

1.用for循环写一个函数,实现从1开始输出到N的正整数. 有两宗实现方法,一种是递归,另一种是非递归 //非递归 void PrintN1(int N){ int i; for(i=1;i<=N;i++){ printf("%d\n",i); } return; } //递归 递归对空间的需求很大,当数字很大的时候,需要很大的内存,当数字是十万的时候递归就崩了 void PrintN2(int N){ if(N){ PrintN2(N-1); printf("%d\n

求最小生成树的两种方法

Kruskal算法核心是加边,先把所有边按照权值从小到大排序,然后在剩下的所有没有被选过的边中,找到最小的边,如果和已经选取的边构成回路则放弃,选取次小边,直到选取了n-1条边为止,这样所有点就都连通了. 每次从边集中选取的权值最小的边的两个顶点如果属于不同的树,就把他们合并(把这条边加入子图),反之则去看下一条边. n个点e条边的情况下,时间复杂度O(e^2),并查集优化之后O(eloge),适用于求稀疏图的最小生成树. int find(int x) { return p[x]==x?x:p