一个讲的比较好的博客:https://blog.csdn.net/qq_27151549/article/details/81390751
这种方法常数最小
typedef long long ll;
void extgcd(ll a,ll b,ll& d,ll& x,ll& y){
if(!b){ d=a; x=1; y=0;}
else{ extgcd(b,a%b,d,y,x); y-=x*(a/b); }
}
ll inverse(ll a,ll n){
ll d,x,y;
extgcd(a,n,d,x,y);
return d==1?(x+n)%n:-1;
}
如果一个数m为素数,那么a^(m-1)≡1 (mod m),那么a的逆元就是a^(m-2),这是根据费马小定理推出来的。
typedef long long ll;
ll pow_mod(ll x, ll n, ll mod){
ll res=1;
while(n>0){
if(n&1)res=res*x%mod;
x=x*x%mod;
n>>=1;
}
return res;
}
ll ans = pow_mod(a,m-2,m);
long long eular(long long n)
{
long long ans = n;
for(int i = 2; i*i <= n; i++)
{
if(n % i == 0)
{
ans -= ans/i; //等价于通项,把n乘进去
while(n % i == 0) //确保下一个i是n的素因数
n /= i;
}
}
if(n > 1)ans -= ans/n; //最后可能还剩下一个素因数没有除
return ans;
}
注意,求出φ(n)以后依旧是mod n。
然后根据a^(φ(n))≡1 (mod n),再拉个快速幂就行了。
typedef long long ll;
const int N = 1e5 + 5;
int inv[N];
void inverse(int n, int p) {
inv[1] = 1;
for (int i=2; i<=n; ++i) {
inv[i] = (ll) (p - p / i) * inv[p%i] % p;
}
}