[模板]乘法逆元
2017-11-09 20:36
162 查看
费马小定理
适用:求某一个数在模意义下的乘法逆元。如果a、p互质,那么有ap−a就是p的倍数,所以有ap≡a(modp),ap−1≡1(modp)。所以只要打一个快速幂就ok了。
code
#include<bits/stdc++.h> using namespace std; int n,p; int power(int x,int k) { int ans=1; while(k) { if(k&1)ans*=x%p; ans%=p; x=x*x%p; k>>=1; } return ans%p; } int main() { scanf("%d%d",&n,&p); printf("1\n"); for(int i=2;i<=n;i++) printf("%d\n",power(i,p-2)); return 0; }
线性求法
适用:某一区间的所有的数在模意义下的乘法逆元、求单个逆元(递归求解)。简单地说就是一个递推。
首先我们有:1−1≡1(modp)
然后,我们设p=k×i+r,r<l,1<i<p再将这个式子放到modp意义下一看:k×i+r≡0(modp)
再两边同时乘上i−1,r−1可以得到:
k×r−1+i−1≡0(modp)
移项:
i−1=−k×r−1(modp)
所以:
i−1≡−[pi]×(pmodi)−1
于是乎我们就可以递推处当前的逆元了:
A[i]=-(p/i)*A[p%i]
然后其实吧,我们还可以通过递归求解,在O(log2p)的时间内求出单个逆元。怎么证明时间复杂度呢:由于我们可以发现pmodi<i/2,所以每次的子问题规模减半,最终递归次数也可见了。
code:
#include<bits/stdc++.h> #define maxn 3000005 using namespace std; int n; long long p; long long ans[maxn]; int main() { scanf("%d%lld",&n,&p); ans[1]=1; for(int i=2;i<=n;i++) ans[i]=(-(p/i)*ans[p%i])%p; for(int i=1;i<=n;i++) printf("%lld\n",ans[i]>0 ? ans[i] : ans[i]+p); return 0; }
相关文章推荐
- 洛谷P3811 【模板】乘法逆元(递推)
- 模板【洛谷P3811】 【模板】乘法逆元
- 洛谷 P3811 【模板】乘法逆元
- Loj-110乘法逆元(线性模板题)
- 乘法逆元模板
- [P3811][模板]乘法逆元
- [洛谷3811]【模板】乘法逆元
- 洛谷 P3811 【模板】乘法逆元
- 【模板】乘法逆元
- codeforces 300C 乘法逆元 (乘法逆元模为素数的模板)
- 洛谷—— P3811 【模板】乘法逆元
- ACM 乘法逆元 模板
- 乘法逆元模板
- 求乘法逆元模板(扩展欧几里得)
- [模板]乘法逆元
- 51nod 1256 乘法逆元 (模板)
- 乘法逆元+排列组合模板
- 乘法逆元 模板
- luogu P3811 【模板】乘法逆元
- 扩展欧几里得、求乘法逆元及其应用、中国剩余定理(互质版和非互质版)、欧拉函数、快速判素数模板