算法:逆元

逆元

定義

一個數aa的倒數a1a^{-1}滿足a×a1=1a \times a^{-1} = 1。取aa的逆元(amod  b)1(a \mod b)^{-1}滿足(amod  b)×(amod  b)1mod  b=1(a \mod b) \times (a \mod b)^{-1} \mod b = 1。其中bb爲質數,aa的逆元(amod  b)1=ab2mod  b(a \mod b)^{-1} = a^{b-2} \mod b

證明

由費馬小定理得ab1mod  b=1a^{b-1} \mod b = 1,即(ab2mod  b)×(amod  b)mod  b=1(a^{b-2} \mod b) \times (a \mod b) \mod b = 1,故(amod  b)1=ab2mod  b(a \mod b)^{-1} = a^{b-2} \mod b
費馬小定理簡單證明如下:取A={1,2,,b1}A = \{1,2, \dots ,b-1\},則Amod  b={1,2,,b1}A \mod b = \{1,2, \dots ,b-1\};取a×A={a,2a,,(b1)a}a \times A = \{a,2a, \dots, (b-1)a\},則a×Amod  b={1,2,,b1}a \times A \mod b = \{1,2, \dots ,b-1\}仍然成立(此處可見下面證明)。取AA中所有元素相乘得SS,取a×Aa \times A中所有元素相乘得ab1×Sa^{b-1} \times S,由{Smod  b=(b1)!mod  bab1×Smod  b=(b1)!mod  b\left\{\begin{array}{cc} S \mod b = (b-1)! \mod b\\ a^{b-1} \times S \mod b = (b-1)! \mod b \end{array}\right.ab1mod  b=1a^{b-1} \mod b = 1
下面用反證法證明a×Amod  b={1,2,,b1}a \times A \mod b = \{1,2, \dots ,b-1\}。對於任意x,ya×A,x<yx,y \in a \times A, x \lt y,假設xmod  b=ymod  bx \mod b = y \mod b,那麼(yx)mod  b=0(y-x) \mod b = 0,由{ymod  a=0xmod  a=0\left\{\begin{array}{cc} y \mod a = 0\\ x \mod a = 0 \end{array}\right.(yx)mod  a=0(y-x) \mod a = 0,由bb爲質數得lcm(a,b)=a×blcm(a, b) = a \times b,故(yx)mod  (a×b)=0(y-x) \mod (a \times b) = 0,因此yxa×by-x \ge a \times b,與x,ya×Ax,y \in a \times A矛盾,由此可得xmod  bymod  bx \mod b \ne y \mod b。因此a×Amod  ba \times A \mod b(b1)(b-1)個互不相同的元素,即a×Amod  b={1,2,,b1}a \times A \mod b = \{1,2, \dots ,b-1\}

思路

利用快速冪aa的逆元ab2mod  ba^{b-2} \mod b

時間複雜度

O(logn)O(\log n)

模板

#include "FP.h"

typedef long long LL;
const LL MOD = 1e9+7;  // the divisor of answer

/**
  * @param a: the number a
  * @return: the inverse of a
  * @other: FP is Fast Power 
  */
LL INV(LL a) {
  return FP(a, MOD-2);
}

應用1

求組合數Cnmmod  bC_n^m \mod b。由Cnm=n!m!(nm)!C_n^m = \frac {n!}{m!(n-m)!}Cnmmod  b=n!m!(nm)!mod  b=(n!mod  b)×(m!mod  b)1×((nm)!mod  b)1mod  bC_n^{m} \mod b = \frac {n!}{m!(n-m)!} \mod b = (n! \mod b) \times (m! \mod b)^{-1}\times((n-m)! \mod b)^{-1}\mod b。先預處理1!,2!,,n!1!,2!,\dots,n!,時間複雜度爲O(n)O(n),再直接求Cnmmod  bC_n^m \mod b,時間複雜度爲O(1)O(1)

模板1

#include "INV.h"

const LL N = 1e6+10;  // the maximum number

LL fac[N];  // the factorial of numbers
LL inv[N];  // the inverse of factorial

/**
  * @other: initialize fac and inv
  */
void init() {
  inv[0] = fac[0] = 1;  // 0! = 1, INV(1) = 1
  for (int i = 1; i < N; ++i) {
    fac[i] = fac[i-1] * i % MOD;  // i! = (i-1)! * i
    inv[i] = INV(fac[i]);
  }
}

/**
  * @param n: the number n
  * @param m: the number m
  * @return: C(n, m)
  */
LL C(LL n, LL m) {
  return fac[n] * inv[m] % MOD * inv[n-m] % MOD;
}

應用2

已知p,q,bp,q,b,求aa滿足a×pmod&ThinSpace;&ThinSpace;b=qmod&ThinSpace;&ThinSpace;ba \times p \mod b = q \mod b。由(a×pmod&ThinSpace;&ThinSpace;b)×(pmod&ThinSpace;&ThinSpace;b)1=(qmod&ThinSpace;&ThinSpace;b)×(pmod&ThinSpace;&ThinSpace;b)1(a \times p \mod b) \times (p \mod b)^{-1} = (q \mod b) \times (p \mod b)^{-1}a=(qmod&ThinSpace;&ThinSpace;b)×(pmod&ThinSpace;&ThinSpace;b)1a = (q \mod b) \times (p \mod b)^{-1}

模板2

#include "INV.h"

/**
  * @param p: the number p
  * @param q: the number q
  * @return: the number a
  */
LL cal(LL p, LL q) {
  return q * INV(p) % MOD;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章