1.不为素数
方法一,拓展欧几里德
1 #include<bits/stdc++.h> 2 using namespace std; 3 long long c,n; 4 long long d(long long a,long long b) 5 { 6 a=a%c;long long ans=1; 7 while(b!=0){ 8 if(b&1) ans=(ans*a)%c; 9 b/=2; 10 a=(a*a)%c; 11 } 12 return ans; 13 } 14 int main() 15 { 16 cin>>n>>c; 17 for(int i=1;i<=n;i++) 18 printf("%lld\n",d(i,c-2)); 19 }
方法二,线性打表
应用范围较小,必须要开很大数组,而且平时用不到。所以……咕咕咕
2.为素数
方法一,费马小定理
因为$a*a^{-1}Ξ1(mod p)$
费马小定理$a^pΞa{(mod p)}$
所以$a^{p-2}$Ξ$a^{-1}(mod p)$
所以$a^{p-2}$为逆元
具体实现
ll meng(ll x,ll k) { ll ans=1; for(;k;k>>=1,x=x*x%p) if(k&1) ans=x*ans%p; return ans; } 调用时meng(a(m),p-2)
这也是最常用的方法。
方法二,拓展欧几里德
阶乘逆元
理解一下,逆元实际上就是$1/?$
而$1/(n+1)!*(n+1)$其实就是$1/(n)!$,这样就求出来逆元了 。
ni[n]=meng(jie[n],p-2); for(ll i=n-1;i>=1;i--)ni[i]=ni[i+1]*(i+1)%p;
完了