线性求逆元
题目链接:ybt高效进阶6-3-3
题目大意
给你 n,p,要你求 1~n 每个数在模 p 意义下的逆元。
思路
线性求逆元的公式就是:
i
n
v
i
=
(
(
p
−
p
/
i
∗
i
n
v
p
m
o
d
i
)
m
o
d
p
+
p
)
m
o
d
p
inv_i=((p-p/i*inv_{p\bmod i})\bmod p+p)\bmod p
invi=((p−p/i∗invpmodi)modp+p)modp
这里给一下证明:
因为是线性,所以假设我们求
i
i
i,那
1
∼
i
−
1
1\sim i-1
1∼i−1 的我们都求出来了。
那
p
p
p 可以表示成
⌊
p
i
⌋
∗
i
+
r
(
0
⩽
r
<
i
)
\left\lfloor\dfrac{p}{i}\right\rfloor*i+r(0\leqslant r<i)
⌊ip⌋∗i+r(0⩽r<i),所以就有
⌊
p
i
⌋
∗
i
+
r
≡
0
(
m
o
d
p
)
\left\lfloor\dfrac{p}{i}\right\rfloor*i+r\equiv0(\bmod\ p)
⌊ip⌋∗i+r≡0(mod p)
然后两边都乘
i
n
v
i
∗
i
n
v
r
inv_i*inv_r
invi∗invr,就有
⌊
p
i
⌋
∗
i
n
v
r
+
i
n
v
i
≡
0
(
m
o
d
p
)
\left\lfloor\dfrac{p}{i}\right\rfloor*inv_r+inv_i\equiv0(\bmod\ p)
⌊ip⌋∗invr+invi≡0(mod p)
i
n
v
i
≡
−
⌊
p
i
⌋
∗
i
n
v
r
(
m
o
d
p
)
inv_i\equiv-\left\lfloor\dfrac{p}{i}\right\rfloor*inv_r(\bmod\ p)
invi≡−⌊ip⌋∗invr(mod p)
然后由于 ( 0 ⩽ r < i ) (0\leqslant r<i) (0⩽r<i), i n v r inv_r invr 是已知的,所以就得出了 i n v i inv_i invi。
代码
#include<cstdio>
using namespace std;
int n, p, inv[3000001];
int main() {
scanf("%d %d", &n, &p);
inv[1] = 1;
for (int i = 2; i <= n; i++)//不开 long long 见祖宗
inv[i] = ((1ll * p - 1ll * p / i * inv[p % i]) % p + p) % p;
for (int i = 1; i <= n; i++) printf("%d\n", inv[i]);
return 0;
}