主要参考:OI-WIKI
为什么要逆元
当一个题目让你求方案数时常要取余,虽然
(a+b)%p=(a%p+b%p)%p
(a−b)%p=(a%p−b%p)%p
(a×b)%p=(a%p×b%p)%p
但是
(ab)%p≠(a%pb%p)%p
由于会出现这种情况,所以就要逆元了
一般情况下,当ax=1时,x 是 a 的倒数,x=1a
毕竟是取余,所以当ax≡1(modp)时, x 叫做 a 关于 p 的逆元,用 a−1 表示
于是 (ab)%p=(a%p×b−1%p)%p
这样就把除法转换成乘法,解决了问题
如何求逆元
前提:gcd(a,p)=1 (本蒟蒻现在才发现模数这么奇怪原来有意图,如
)
费马小定理
∵ap≡a(modp)∴ap−2≡1a(modp)
证明:OI-WIKI(蒟蒻不会)
所以说a−1≡ap−2(modp)
复杂O(logp)
扩展欧几里得
ax+py=1的一组解 (x,y) ,x 是 a 关于 p 的逆元, y 是 p 关于 a 的逆元
证明:两边同时模 p
ax+py=1ax%p+py%p=1%p ax%p=1%p ax≡1(modp)
所以 x 是 a 关于 p 的逆元,反之可以证明 y
复杂O(logp)
连续的逆元
连续的逆元
如果直接暴力求,效率低,很有可能超时,如何线性(O(n))求呢?
首先 1−1≡1(modp)
然后,设 p=k∗i+r,r<i,l<i<p ,放到(modp) 下就成了 k∗i+r≡0(modp)
两边同时乘上i−1和r−1可得
k∗i∗i−1∗r−1+r∗i−1∗r−1≡0(modp)
k∗r−1+i−1≡0(modp)
i−1≡−k∗r−1(modp)
i−1≡−⌊ip⌋∗(pmodi)−1(modp)
于是就可以从前面推出当前的逆元了,A[1]=1,A[i]=(p−p/i)∗A[p%i]
用 p−⌊pi⌋防止出现负数,时间复杂度O(n)
阶乘的逆元
可以先处理 n! 的逆元,可以发现对于一个 1≤i<n,都有1i!=1(i+1)!∗(i+1)
所以 i!的逆元A[i]=A[i+1]∗(i+1)%p,A[n] 先求出来,时间复杂度O(logp+n)
求任意 n 个数的逆元
先算出前缀积 si 并预处理出 sn 的逆元 svn ,
与阶乘的逆元相同,svi=svi+1∗ai+1%p,1≤i<n 用这种抵消的方法可以O(n)处理出sv
求出了sv,a−1i可以用si−1∗svi求得,时间复杂度O(logp+n)
本文作者:小蒟蒻laf
本文链接:https://www.cnblogs.com/KonjakLAF/p/14224309.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步