首先求的是1~n中间所有数的逆元,模数为m。
朴素算法
就是把区间中的所有逆元单个求出来,时间为 O ( n l o g n ) O(nlogn) O(nlogn)
递推算法
先把时间复杂度给出来:
O
(
n
)
O(n)
O(n)
设x的逆元为
f
(
x
)
f(x)
f(x)
先来两个知识
1. f ( m − i ) = − f ( i ) f(m-i)=-f(i) f(m−i)=−f(i)
证明如下:
因为
f
(
i
)
∗
i
≡
1
(
m
o
d
m
)
f(i)*i≡1\pmod m
f(i)∗i≡1(modm)
所以
f
(
i
)
∗
(
−
i
)
≡
−
1
(
m
o
d
m
)
f(i)*(-i)≡-1\pmod m
f(i)∗(−i)≡−1(modm)
即
−
f
(
i
)
∗
(
m
−
i
)
≡
1
(
m
o
d
m
)
-f(i)*(m-i)≡1\pmod m
−f(i)∗(m−i)≡1(modm)
又因为
f
(
m
−
i
)
∗
(
m
−
i
)
≡
1
(
m
o
d
m
)
f(m-i)*(m-i)≡1\pmod m
f(m−i)∗(m−i)≡1(modm)
所以
f
(
m
−
i
)
=
−
f
(
i
)
f(m-i)=-f(i)
f(m−i)=−f(i)
2. f ( i ) ≡ k ∗ f ( k ∗ i ) ( m o d m ) f(i)≡k*f(k*i)\pmod m f(i)≡k∗f(k∗i)(modm)
证明如下:
因为
{
f
(
k
∗
i
)
∗
k
∗
i
≡
1
(
m
o
d
m
)
f
(
i
)
∗
i
≡
1
(
m
o
d
m
)
\begin{cases}f(k*i)*k*i≡1\pmod m\\f(i)*i≡1\pmod m\end{cases}
{f(k∗i)∗k∗i≡1(modm)f(i)∗i≡1(modm)
所以
f
(
i
)
∗
i
≡
f
(
k
∗
i
)
∗
k
∗
i
(
m
o
d
m
)
f(i)*i≡f(k*i)*k*i\pmod m
f(i)∗i≡f(k∗i)∗k∗i(modm)
即
f
(
i
)
≡
k
∗
f
(
k
∗
i
)
(
m
o
d
m
)
f(i)≡k*f(k*i)\pmod m
f(i)≡k∗f(k∗i)(modm)
由以上两个知识可以得出 f ( n ) = ( f ( m % n ) ∗ ( m / n ) % m + m ) % m f(n)=(f(m\%n)*(m/n)\%m+m)\%m f(n)=(f(m%n)∗(m/n)%m+m)%m