乘法逆元的解法及证明

写在前面

刷题过程中,为了避免高精度的整数运算,常常会要求答案对某个数取模。但这衍生了一个新问题,如果运算过程中涉及了除法,如 a b \frac{a}{b} ba,如果先对a和b取模再做除法,会导致答案错误。比如:
20 5   m o d   10 = 4 \frac{20}{5}\ mod\ 10 = 4 520 mod 10=4
但是,
20   m o d   10 5   m o d   10 = 0 \frac{20\ mod\ 10}{5\ mod\ 10} = 0 5 mod 1020 mod 10=0

为了解决这个问题,我们需要学习新知识:模运算下的乘法逆元。

乘法逆元

什么是逆元呢?百度百科告诉我们:逆元是指一个可以取消另一给定元素运算的元素。

比如,在实数的加法中,任意实数 a 和它的相反数 -a,互为加法逆元。因为对于任意实数 x,加上a之后,再加上-a,仍然等于 x,换言之,-a取消xa的加法运算。

再比如,在实数的乘法中,任意不为0的实数b和它的倒数 1 b \frac{1}{b} b1,互为乘法逆元。因为对于任意实数x,乘上b之后,在乘上 1 b \frac{1}{b} b1,仍然等于x,换言之, 1 b \frac{1}{b} b1取消xb 的乘法运算。

接下来看看模运算下的乘法逆元定义:如果两个整数ab 满足 ( a ∗ b − 1 )   m o d   p = 0 (a*b-1)\ mod\ p = 0 (ab1) mod p=0,即 a ∗ b ≡ 1 ( m o d   p ) a*b≡1(mod\ p) ab1(mod p),则称,ab 互为模 p 的乘法逆元。

换言之,如果整数a, b, p 满足 a ∗ b ≡ 1 ( m o d   p ) a*b≡1(mod\ p) ab1(mod p),那么 b 可以取消 a 和任意整数x在模p时的乘法,即 ab 互为模 p 的乘法逆元。即 x ∗ a ∗ b ≡ x ( m o d   p ) x*a*b≡x (mod\ p) xabx(mod p),证明过程如下:

x   m o d   p = x ( a ∗ b − 1 ) + x   m o d   p = ( x ∗ a ∗ b − x ) + x   m o d   p = x ∗ a ∗ b   m o d   p \begin{aligned} x\ mod\ p &= x(a*b-1)+x \ mod\ p \\ &= (x*a*b-x)+x \ mod \ p \\ &= x*a*b \ mod \ p \end{aligned} x mod p=x(ab1)+x mod p=(xabx)+x mod p=xab mod p

举个实际的例子:比如 1012 互为模7时的乘法逆元。然后再找个整数,比如 18,此时有:

18   m o d   7 = 4 18\ mod\ 7 = 4 \\ 18 mod 7=4

另有,

18 ∗ 10 ∗ 12   m o d   7 = 2160   m o d   7 = 4 \begin{aligned} 18 * 10 * 12\ mod\ 7 &= 2160\ mod\ 7 \\ &= 4 \end{aligned} 181012 mod 7=2160 mod 7=4

何时存在乘法逆元

结论

先说结论:ap 互质存在a关于模p的乘法逆元b 的充分必要条件。

存在逆元 → 互质

证明 ap 互质存在乘法逆元b必要条件。不妨先假设 ab 互为模p时的乘法逆元,且ap的最大公约数为d,则有:

( a ∗ b − 1 )   m o d   p = 0 (a*b-1)\ mod\ p = 0 (ab1) mod p=0

显然,a*b-1pn 倍,n 为整数,则上式转化为:

( a ∗ b − 1 ) = n p (a*b-1)=np (ab1)=np

将等式中的apd代替,则等式转化为:

( x ∗ d ∗ b − 1 ) = n ∗ y ∗ d ( x ∗ d ∗ b − n ∗ y ∗ d ) = 1 ( x ∗ b − n ∗ y ) ∗ d = 1 x ∗ b − n ∗ y = 1 d \begin{aligned} (x*d*b-1)&=n*y*d \\ (x*d*b - n*y*d) &= 1 \\ (x*b - n*y)*d &= 1 \\ x*b - n*y &= \frac{1}{d} \\ \end{aligned} (xdb1)(xdbnyd)(xbny)dxbny=nyd=1=1=d1

显然,x*b-n*y是一个整数,所以仅当d1时,即ap互质时,上述等式才可能成立。

互质 → 存在逆元

证明 ap 互质存在乘法逆元b充分条件

在证明之前先来回忆一下辗转相除法:
g c d ( a , p ) = g c d ( p , a   m o d   p ) \begin{aligned} gcd(a,p) &= gcd(p, a\ mod\ p) \\ \end{aligned} gcd(a,p)=gcd(p,a mod p)

不妨用r来表示模运算的结果:
g c d ( a , p ) = g c d ( p , r 1 ) = g c d ( r 1 , r 2 ) = . . . = g c d ( r m − 1 , r m ) = 1    / / 因 为 a 与 p 互 质 \begin{aligned} gcd(a,p) &= gcd(p, r_1) \\ &= gcd(r_1,r_2) \\ &= ... \\ &= gcd(r_{m-1}, r_m) \\ &= 1\ \ //因为a与p互质 \end{aligned} gcd(a,p)=gcd(p,r1)=gcd(r1,r2)=...=gcd(rm1,rm)=1  //ap

将上式用除法表示,则有:
a = n 1 p + r 1 p = n 2 r 1 + r 2 r 1 = n 3 r 2 + r 3 . . . = . . . r m − 3 = n m − 1 r m − 2 + r m − 1 r m − 2 = n m r m − 1 r m − 1 = 1 r m = 0 \begin{aligned} a &= n_1p + r_1\\ p &= n_2r_1 + r_2 \\ r_1 & = n_3r_2 + r_3 \\ ... &= ... \\ r_{m-3} &= n_{m-1}r_{m-2} + r_{m-1} \\ r_{m-2} &= n_{m}r_{m-1} \\ r_{m-1} &= 1\\ r_{m} &= 0 \\ \end{aligned} apr1...rm3rm2rm1rm=n1p+r1=n2r1+r2=n3r2+r3=...=nm1rm2+rm1=nmrm1=1=0

由上述的m+2个等式移项可得:
r 1 = a − n 1 p r 2 = p − n 2 r 1 . . . = . . . r i = r i − 2 − n i ∗ r i − 1 r m − 1 = r m − 3 − n m − 1 r m − 2 特 别 的 , 1 = r m − 1 \begin{aligned} r_1 &= a - n_1p \\ r_2 &= p - n_2r_1 \\ ... &= ... \\ r_{i} &= r_{i-2} - n_{i}*r_{i-1} \\ r_{m-1} &= r_{m-3} - n_{m-1}r_{m-2} \\ 特别的,1 &= r_{m-1} \\ \end{aligned} r1r2...rirm11=an1p=pn2r1=...=ri2niri1=rm3nm1rm2=rm1

将 rm-1,rm-2 … 以及 r1 依次代入
1 = r m − 1 1 = r_{m-1} 1=rm1

可以得到用 ap 以及 ni表示的等式:
a x + p y = 1 ax+py=1 ax+py=1

其中,xy 为 n1,n2,n3 … 的加减乘的运算结果,显然为整数

得证,当 ap 互质时,存在整数xy 满足
a x + p y = 1 a x − 1 = p y ( a x − 1 )   m o d   p = 0 a x ≡ 1   ( m o d   p ) \begin{aligned} ax+py &= 1 \\ ax-1 &= py \\ (ax-1)\ mod\ p &= 0 \\ ax &≡ 1\ (mod\ p) \end{aligned} ax+pyax1(ax1) mod pax=1=py=01 (mod p)

即,当 ap 互质时,存在整数xa互为模p时的乘法逆元。

如何计算乘法逆元

扩展欧几里得算法

回忆一下欧几里得的递归过程:
g c d ( a , b ) = g c d ( b , a   m o d   b ) = g c d ( b , a − b ⌊ a b ⌋ ) \begin{aligned} gcd(a,b) &= gcd(b, a\ mod\ b) \\ &= gcd(b, a - b\lfloor \frac{a}{b} \rfloor) \end{aligned} gcd(a,b)=gcd(b,a mod b)=gcd(b,abba)

ab 互质时,有 x,y,x',y' 满足:
{ a x + b y = 1 b x ′ + ( a − b ⌊ a b ⌋ ) y ′ = 1 \left\{ \begin{aligned} ax+by=1 \\ bx'+ (a - b\lfloor \frac{a}{b} \rfloor)y' = 1\\ \end{aligned} \right. ax+by=1bx+(abba)y=1

将上式合并移项:
b x ′ + ( a − b ⌊ a b ⌋ ) y ′ = a x + b y a ( x − y ′ ) + b ( y − ( x ′ − ⌊ a b ⌋ ) y ′ ) = 0 \begin{aligned} bx'+ (a - b\lfloor \frac{a}{b} \rfloor)y'&=ax+by \\ a(x-y') + b(y-(x'-\lfloor \frac{a}{b} \rfloor)y')&=0 \end{aligned} bx+(abba)ya(xy)+b(y(xba)y)=ax+by=0

x,y,x',y' 满足下述关系,则对于任意 ab 上述公式都能成立。
{ x = y ′ y = ( x ′ − ⌊ a b ⌋ ) y ′ \left\{ \begin{aligned} x &= y' \\ y &= (x'-\lfloor \frac{a}{b} \rfloor)y' \\ \end{aligned} \right. xy=y=(xba)y

😯好巧,这就是我们要寻找的x,yx',y'的计算公式。另外,当 b = 0,即到达欧几里得算法的递归边界时,令 x = 1, y = 0 即可满足ax+by=1(此时的a显然为1)。

于是我们得到了下述代码,最终得到的 x 即为 a 在模 b 时的乘法逆元,当然前提是函数的返回值为1,即 a 与 b 互质

int exgcd(int a,int b,int &x,int &y)
{
    if(b==0) {
        x=1;y=0;
        return a;
    }
    int r = exgcd(b,a%b,x,y);
    int t = y;
    y = x-(a/b)*y;
    x = t;
    return r;
}

费马小定理 & 快速幂

费马小定理:若 p 为素数,且 gcd(a, p) = 1,则满足
a p − 1 ≡ 1   ( m o d   p ) a ∗ a p − 2 ≡ 1   ( m o d   p ) \begin{aligned} a^{p-1} ≡ 1\ (mod\ p) \\ a*a^{p-2} ≡ 1\ (mod\ p) \end{aligned} ap11 (mod p)aap21 (mod p)

于是,a 在模 p 时的乘法逆元为 a p − 2 a^{p-2} ap2,可用快速幂求得。

inline int quick_power(int a, int b, int p) {
  int ans = 1;
  a = (a % p + p) % p;
  for (; b; b >>= 1) {
    if (b & 1) ans = (a * ans) % p;
    a = (a * a) % p;
  }
  return ans;
}
// quick_power(a, p-2, p) 即为 a 的乘法逆元。

值得注意的是,该算法仅在 p 为素数时有效,而扩欧并没有该限制。

线性求1到n中每个数的逆元

现在要求1到n中每个数i在模p时的乘法逆元。

特别的,i = 1时,其乘法逆元i-11

当 i > 1 时,不妨先设:
{ k = ⌊ p i ⌋ j = p   m o d   i \left\{ \begin{aligned} k &= \lfloor\frac{p}{i}\rfloor \\ j &= p\ mod\ i \\ \end{aligned} \right. kj=ip=p mod i
则有:
{ p ≡ 0   ( m o d   p ) ( k ∗ i + j ) ≡ 0   ( m o d   p ) ( k ∗ i + j ) ∗ i − 1 ∗ j − 1 ≡ 0   ( m o d   p ) k ∗ j − 1 + i − 1 ≡ 0   ( m o d   p ) − k ∗ j − 1 ≡ i − 1   ( m o d   p ) − ⌊ p i ⌋ ∗ ( p   m o d   i ) − 1 ≡ i − 1   ( m o d   p ) \left\{ \begin{aligned} p &≡ 0\ (mod\ p) \\ (k*i +j) &≡ 0\ (mod\ p) \\ (k*i +j)*i^{-1}*j^{-1} &≡ 0\ (mod\ p) \\ k*j^{-1}+i^{-1} &≡ 0\ (mod\ p) \\ -k*j^{-1} &≡i^{-1}\ (mod\ p) \\ -\lfloor\frac{p}{i}\rfloor *(p\ mod\ i)^{-1} &≡i^{-1} \ (mod\ p) \\ \end{aligned} \right. p(ki+j)(ki+j)i1j1kj1+i1kj1ip(p mod i)10 (mod p)0 (mod p)0 (mod p)0 (mod p)i1 (mod p)i1 (mod p)

而且,在递推过程中,当我们要求 i − 1 i^{-1} i1时,对于任意的 ( p   m o d   i ) − 1 (p\ mod\ i)^{-1} (p mod i)1都是已知的啦(因为 p mod i肯定小于 i),所以可根据 ( p   m o d   i ) − 1 (p\ mod\ i)^{-1} (p mod i)1 通过常数次运算得到 i − 1 i^{-1} i1
i − 1 ≡ { 1 , i = 1 − ⌊ p i ⌋ ( p   m o d   i ) − 1 , i > 2   ( m o d   p ) i^{-1}≡\left\{ \begin{aligned} 1&, i = 1 \\ -\lfloor\frac{p}{i}\rfloor(p\ mod\ i)^{-1}&, i > 2 \\ \end{aligned} \right. \ (mod\ p) i11ip(p mod i)1,i=1,i>2 (mod p)

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

求任意n个整数的乘法逆元

设有 n 个整数,分别为 a1,a2,a3…,对应的逆元为a1-1,a2-1,a3-1…。

设Si 为 a1 到 ai i 个数的乘积,Si-1 为 a1-1 到 ai-1 i 个数的乘积。那么 Si 与 Si-1 互为逆元。证明过程如下:

∏ i = 1 n a i ∗ a i − 1 ≡ 1   m o d   p ∏ i = 1 n a i ∗ ∏ i = 1 n a i − 1 ≡ 1   m o d   p S n ∗ S n − 1 ≡ 1   m o d   p \begin{aligned} \prod_{i = 1}^{n}{a_i*{a_i}^{-1}} &≡ 1\ mod\ p \\ \prod_{i = 1}^{n}a_i*\prod_{i = 1}^{n}{a_i}^{-1} &≡ 1\ mod\ p \\ S_n*{S_n}^{-1} &≡ 1\ mod\ p \\ \end{aligned} i=1naiai1i=1naii=1nai1SnSn11 mod p1 mod p1 mod p

接下来,我们可以先求出 S1 到 Sn,然后通过扩展欧几里得或者快速幂求出 Sn 的乘法逆元 Sn-1

又有
S i − 1 ∗ a i + 1 − 1 ∗ a i + 1 ≡ S i − 1   ( m o d   p ) S i + 1 − 1 ∗ a i + 1 ≡ S i − 1   ( m o d   p ) \begin{aligned} {S_i}^{-1}*{a_{i+1}}^{-1}*a_{i+1} &≡ {S_i}^{-1}\ (mod\ p) \\ {S_{i+1}}^{-1}*a_{i+1} &≡ {S_i}^{-1}\ (mod\ p) \end{aligned} Si1ai+11ai+1Si+11ai+1Si1 (mod p)Si1 (mod p)

换言之,我们可以利用 ai可以取消ai-1乘法运算的性质,由Si-1 计算出 Si-1-1

这样就可以O(n)的计算出所有的 Si-1

最后,由Si-1以及Si 计算出所有的 ai-1
a i − 1 ≡ S i − 1 ∗ S i − 1   ( m o d   p ) {a_i}^{-1} ≡ S_{i-1}*{S_{i}}^{-1}\ (mod\ p) ai1Si1Si1 (mod p)

s[0] = 1;
for (int i = 1; i <= n; ++i) s[i] = s[i - 1] * a[i] % p;
sv[n] = quick_power(s[n], p - 2);
for (int i = n; i >= 1; --i) sv[i - 1] = sv[i] * a[i] % p;
for (int i = 1; i <= n; ++i) inv[i] = sv[i] * s[i - 1] % p;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值