逆元

求解一(费马小定理)

p p p是一个质数,并且 a % p ≠ 0 a \% p \not= 0 a%p​=0,则有 a p − 1 ≡ 1 ( m o d p ) a ^ {p - 1} \equiv 1 \pmod p ap−1≡1(modp), a p − 2 ≡ a − 1 a ^ {p - 2} \equiv a ^ {-1} ap−2≡a−1,即可得到逆元。

int quic_pow(int a, int n, int mod) {
    int ans = 1;
    while(n) {
        if(n & 1) ans = (ans * a) % mod;
        a = (a * a) % mod;
        n >>= 1;
    }
    return ans;
}
int inv(int a, int p) {
    return quick_pow(a, p - 2, p);
}

求解二(拓展欧几里德)

我们知道拓展欧几里德算法可以求解 a x + b y = g c d ( a , b ) ax + by = gcd(a, b) ax+by=gcd(a,b),对逆元考虑假设有 a ∗ x + b ∗ y = 1 a * x + b * y = 1 a∗x+b∗y=1那么显然有 a ∗ x ≡ 1 ( m o d b ) a * x \equiv 1 \pmod b a∗x≡1(modb),这不就出来了吗, x x x就是 a a a模 b b b下的逆元,当然了这里也要有 a , b a, b a,b互质。

int exgcd(int a, int b, int & x, int & y) {
    if(!b) {
        x = 1, y = 0;
        return a;
    }
    int gcd = exgcd(b, a % b, x, y);
    int temp = x;
    x = y;
    y = temp - a / b * y;
    return gcd;
}
int main() {
    int a, mod, inv, t;
    exgcd(a, mod, inv, t);
    return 0;
}

求解三(线性求解逆元)

我们假定有 m o d = k ∗ a + b , k = m o d a , b = m o d % a , b < a mod = k * a + b, k = \frac{mod} {a}, b = mod \% a,b < a mod=k∗a+b,k=amod​,b=mod%a,b<a

k ∗ a + b ≡ 0 ( m o d m o d ) k * a + b \equiv 0 \pmod {mod} k∗a+b≡0(modmod)

同时乘以 a − 1 b − 1 a ^ {-1}b^{-1} a−1b−1

得 k ∗ b − 1 + a − 1 ≡ 0 ( m o d m o d ) k * b ^{-1} + a ^{-1} \equiv 0 \pmod {mod} k∗b−1+a−1≡0(modmod)

a − 1 ≡ − k ∗ b − 1 ( m o d m o d ) a ^{-1} \equiv -k * b ^ {-1} \pmod {mod} a−1≡−k∗b−1(modmod)

a − 1 ≡ m o d ∗ b − 1 − k ∗ b − 1 ( m o d m o d ) a ^ {-1} \equiv mod * b ^{-1} - k * b^ {-1} \pmod {mod} a−1≡mod∗b−1−k∗b−1(modmod)

所以我们就推导完了。

int inv[n], mod = 100007, n = mod;
inv[1] = 1;
for(int i = 2; i < n; i++) {
	inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod;
}

求解四( C n m C _{n} ^ {m} Cnm​中的逆元求解)

a ! − 1 = n a! ^ {-1} = n a!−1=n那么我们不难发现 ( a − 1 ) ! − 1 = a ! − 1 ∗ a (a - 1) ! ^ {-1} = a! ^{-1} * a (a−1)!−1=a!−1∗a

void init() {
    fac[0] = 1;
    for(int i = 1; i < N; i++)
        fac[i] = (fac[i - 1] * i) % mod;
    inv[N - 1] = qpow(fac[N - 1], mod - 2);
    for(int i = N - 2; i >= 0; i--)
        inv[i] = (inv[i + 1] * (i + 1)) % mod;
}