逆元是求ax≡1(mod p)中的x的最小正整数,常应用于 除法取模。
存在这样的x的条件是a与p互素,即只有当a与p互素时,逆元存在
求逆元有三种常用的方式
扩展欧几里德(要求a与p互素)
int extgcd(int a, int b, int &x, int &y) { int d = a; if(b != 0) { d = extgcd(b, a%b, y, x); y -= (a / b) * x; } else x = 1, y = 0; return d; } int mod_inv(int a, int p) { int x, y; extgcd(a, p, x, y); return (x%p + p) % p; }
费马小定理(要求p为素数,且a与p互素)
LL mod_pow(LL a, LL b, LL p) { LL ans = 1; a %= p; while(b>0) { if(b & 1) ans = ans * a % p; a = a * a % p; b >>= 1; } return ans; } LL mod_inv(LL a, LL p) { return mod_pow(a, p-2, p); }
线性时间求逆元(要求p为素数,常用于a较小且需要求出大量逆元的时候)
const int N=50010; int inv[N]; void inv_init(int p) { inv[1] = 1; for(int i = 2; i < N; i++) inv[i] = (p - p / i) * inv[p % i] % p; }