[模板]乘法逆元

来源:互联网 发布:otsu算法 编辑:程序博客网 时间:2024/05/18 06:21

费马小定理

适用:求某一个数在模意义下的乘法逆元。
如果ap互质,那么有apa就是p的倍数,所以有apa(modp)ap11(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; }

线性求法

适用:某一区间的所有的数在模意义下的乘法逆元、求单个逆元(递归求解)。
简单地说就是一个递推。
首先我们有:111(modp)
然后,我们设p=k×i+r,r<l,1<i<p再将这个式子放到modp意义下一看:k×i+r0(modp)
再两边同时乘上i1,r1可以得到:
k×r1+i10(modp)
移项:
i1=k×r1(modp)
所以:
i1[pi]×(pmodi)1
于是乎我们就可以递推处当前的逆元了:
A[i]=-(p/i)*A[p%i]
然后其实吧,我们还可以通过递归求解,在O(log2p)的时间内求出单个逆元。怎么证明时间复杂度呢:由于我们可以发现pmodi<i/2,所以每次的子问题规模减半,最终递归次数也可见了。
code:

#include<bits/stdc++.h>#define maxn 3000005using 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; }
原创粉丝点击