逆元
前置知识
单位元
在一个集合中,对于某种运算,如果对于任何的集合元素 a,和元素 e 运算,得到还是集合元素 a 本身,则称 e 为这个运算下的单位元。
在加法运算中,对于任意实数
在乘法运算中,对于任意实数
模乘的单位元是
逆元
在一个集合中,对于某种运算 ,如果任意两个元素的运算结果等于单位元,则称这两个元素互为逆元。
模意义下的乘法逆元
若
逆元即数论中的广义倒数。
费马小定理
若p为质数,则
或对于任意整数a,有
欧拉函数
当n是质数时,有
欧拉函数是积性函数,即对任意满足
的整数a,b,有 特别地,当n是奇数时
求一个数的欧拉函数值:在质因数分解的同时求解即可
1 | int eular_phi(int n){ |
欧拉定理
若
则对于费马小定理,有更一般的结论:
应用
求除法的模运算时,经常会因为精度或溢出问题而导致结果产生误差。
故我们可以将求
将除法转为乘法,精度问题便就解决了
扩展欧几里得定理求逆元
给定正整数a,b,求满足
的x的最小正整数解,若无解返回-1
结论
- 当a与b不互质时,逆元必定不存在
- 当a与b互质时,有
对应系数可得:
原式可以由
模板
1 | void exgcd(int a, int b, int &x, int &y){ |
费马小定理
给定素数p和正整数a,求满足
的最小正整数x,若不存在返回-1
此时模数固定为素数,故直接可以用费马小定理求解
当a为p的倍数时,
根据费马小定理有
则
代码
1 | int qpow(long long a, int b){ |
线性求逆元
对于求一连串数字模p的逆元,上两种方法容易超时,用这种方法更快一些
结论
(证明见oi-wiki)
有递推式
代码
1 | void liner(ll n, ll p){ |
线性求任意逆元
首先我们求出n个数的前缀积
又因为
求出所有前缀积的逆元后,我们可以让前缀积的逆元乘i-1的前缀积来消除其他逆元,以得到
1 | s[0]=1; |