转载自 j z _ t e r r y \rm jz\_terry jz_terry的博客
简述
本文要讲的是一种 O ( n ) \mathcal{O(n)} O(n) 算法,用于求 1 ∼ n 1\sim n 1∼n 所有数在膜 p p p 意义下的逆元。
算法
下面给出求 x x x 在膜 p p p 意义下逆元的过程:
假设
p
=
a
x
+
b
p=ax+b
p=ax+b ,则有
a
x
+
b
≡
0
(
m
o
d
p
)
ax+b\equiv 0 \pmod p
ax+b≡0(modp)
式子两边同时除以
x
b
xb
xb ,得
a
x
+
b
x
b
≡
0
(
m
o
d
p
)
\dfrac{ax+b}{xb}\equiv 0 \pmod p
xbax+b≡0(modp)
整理得
a
⋅
b
−
1
+
x
−
1
≡
0
(
m
o
d
p
)
a·b^{-1}+x^{-1}\equiv 0 \pmod p
a⋅b−1+x−1≡0(modp)
即
x
−
1
≡
−
a
⋅
b
−
1
(
m
o
d
p
)
x^{-1}\equiv -a·b^{-1} \pmod p
x−1≡−a⋅b−1(modp)
∵
p
=
a
x
+
b
∵p=ax+b
∵p=ax+b
∴
a
=
⌊
p
x
⌋
,
b
=
p
 
m
o
d
 
x
∴a=\bigg\lfloor\dfrac px \bigg\rfloor,b=p\bmod x
∴a=⌊xp⌋,b=pmodx
将其带入即得
x
−
1
≡
−
⌊
p
x
⌋
×
(
p
 
m
o
d
 
x
)
−
1
x^{-1}\equiv-\bigg\lfloor\dfrac px \bigg\rfloor ×(p\bmod x)^{-1}
x−1≡−⌊xp⌋×(pmodx)−1
注意,为了避免出现负数,递推式中的
−
p
/
x
-p/x
−p/x 实际应是
p
−
p
/
x
p-p/x
p−p/x 。
设
f
i
f_i
fi 表示
i
i
i 在膜
p
p
p 意义下的逆元,则有:
f
i
=
(
p
−
p
/
x
)
×
f
p
 
m
o
d
 
i
 
m
o
d
 
p
f_i=(p-p/x)×f_{p\bmod i}\bmod p
fi=(p−p/x)×fpmodimodp (
/
/
/为整除)
边界条件是 f 1 = 1 f_1=1 f1=1
这样就可以求 1 ∼ n 1 \sim n 1∼n 所有数在膜 p p p 意义下的逆元了
U P D o n 2019 / 7 / 28 \rm UPD\ on\ 2019/7/28 UPD on 2019/7/28 补充一种自己口胡的证法
∵
f
p
 
m
o
d
 
i
×
p
 
m
o
d
 
i
≡
1
(
m
o
d
p
)
\because f_{p\bmod i}\times p\bmod i\equiv 1\pmod p
∵fpmodi×pmodi≡1(modp)
∴
f
p
 
m
o
d
 
i
×
(
p
−
⌊
p
i
⌋
×
i
)
≡
1
(
m
o
d
p
)
\therefore f_{p\bmod i}\times(p-\bigg\lfloor\dfrac pi\bigg\rfloor\times i)\equiv 1 \pmod p
∴fpmodi×(p−⌊ip⌋×i)≡1(modp)
根据乘法分配律化简,得
−
⌊
p
i
⌋
×
i
×
f
p
 
m
o
d
 
i
≡
1
(
m
o
d
p
)
-\bigg\lfloor\dfrac pi\bigg\rfloor\times i\times f_{p\bmod i}\equiv 1\pmod p
−⌊ip⌋×i×fpmodi≡1(modp)
两边同乘
f
i
f_i
fi 得
−
⌊
p
i
⌋
×
f
p
 
m
o
d
 
i
≡
f
i
(
m
o
d
p
)
-\bigg\lfloor\dfrac pi\bigg\rfloor\times f_{p\bmod i}\equiv f_i \pmod p
−⌊ip⌋×fpmodi≡fi(modp)
即
f
i
≡
−
p
/
i
×
f
p
 
m
o
d
 
i
(
m
o
d
p
)
f_i \equiv -p/i\times f_{p\bmod i} \pmod p
fi≡−p/i×fpmodi(modp) (
/
/
/为整除)
为避免出现负数,
−
p
/
i
-p/i
−p/i 应变为
p
−
p
/
i
p-p/i
p−p/i ,该变形对上式的正确性没有影响。
U P D o n 2019 / 7 / 30 \rm UPD\ on\ 2019/7/30 UPD on 2019/7/30 补充例题及程序
例题: 洛 谷 P 3811 【 模 板 】 乘 法 逆 元 \sf 洛谷P3811 【模板】乘法逆元 洛谷P3811【模板】乘法逆元
就是个模板题,下面是程序
#include<cstdio>
int n,p,inv[3000010];
char cw[1<<21],t[20]; int p1,p2=-1;
inline void flush() { fwrite(cw,1,p2+1,stdout),p2=-1; }
inline void print(int x) { //快写
if (p2>(1<<20)) flush();
do { t[++p1]=x%10^48; }while (x/=10);
do { cw[++p2]=t[p1]; }while (--p1);
cw[++p2]='\n';
}
int main() {
scanf("%d%d",&n,&p);
inv[1]=1; puts("1");
for (int i=2; i<=n; ++i) {
inv[i]=1ll*inv[p%i]*(p-p/i)%p; //递推式
print(inv[i]);
}
flush();
return 0;
}