求逆
考虑倍增。
若已经求出 A×B′≡1(modxn),我们希望求出 B 使得 A×B≡1(modx2n)。
有:
B−B′≡0(modxn)
(B−B′)2≡0(modx2n)
B2−2BB′+B′2≡0(modx2n)
两边同乘 A,有:
B−2B′+AB′2≡0(modx2n)
所以:
B≡2B′−AB′2(modx2n)
注意应该倍增到最小的 2t 使得 2t≥n。
时间复杂度 O((n+n2+n4+⋯)logn)=O(nlogn)。
带余除法
比较智慧。
考虑定义一个操作 AR(x)=A(1x)=n∑i=0aixn−i。其实就是把系数翻转。
那么:
F(x)≡Q(x)G(x)+R(x)(modxn)
F(1x)≡Q(1x)G(1x)+R(1x)(modxn)
xnF(1x)≡xn−mQ(1x)xmG(1x)+xnR(1x)(modxn)
FR(x)≡QR(x)GR(x)+xn−m+1RR(x)(modxn)
FR(x)≡QR(x)GR(x)(modxn−m)
QR(x)≡FR(x)GR(x)−1(modxn−m)
注意到 Q(x) 的最高项次数恰为 n−m,所以这样即可求得 Q(x),进而求出 R(x)。
时间复杂度 O(nlogn)。
ln
考虑利用多项式求导,有:
B(x)≡lnA(x)(modxn)
B′(x)≡A′(x)A(x)(modxn)
这样就能求出 B′(x),进而求出 B(x)。
时间复杂度 O(nlogn)。
exp
考虑泰勒展开。对于一个光滑函数 g(x),我们有:
g(x)=g(x0)+11!g′(x0)(x−x0)+12!g′′(x0)(x−x0)2+⋯
考虑倍增。假设我们已经求出了 B0(x) 使得 A(x)≡lnB0(x)(modxn),我们现在希望求出 B(x) 使得 A(x)≡lnB(x)(modx2n)。那么令 g 为 ln,x 为 B(x),x0 为 B0(x)。
注意到 B(x)≡B0(x)(modxn),所以 (B(x)−B0(x))2≡0(modx2n)。所以有:
ln(B(x))≡ln(B0(x))+B(x)−B0(x)B0(x)(modx2n)
B0(x)(A(x)−ln(B0(x))+1)≡B(x)(modx2n)
做一次 ln 和乘法即可。
注意一些实现细节,比如 ln(B0(x)) 应该在 modx2n 意义下算。
时间复杂度 O((n+n2+n4+⋯)logn)=O(nlogn)。
快速幂
B(x)≡A(x)k(modxn)
lnB(x)≡klnA(x)(modxn)
B(x)≡eklnA(x)(modxn)
所以先 ln 再 exp 即可。
注意为了保证 [x0]A(x)=1 需要先提公因式 axp。
开方
相当于 k≡12 的快速幂。
为了保证 [x0]A(x)=1 仍然提公因数 a(因为这项一定不是 0)。那么求一个 a 的二次剩余再乘回去即可。
多点求值
发现 F(x0)=F(x)mod(x−x0)。因为 F(x)=Q(x)G(x)+R(x),而且 G(x0)=0。
考虑分治求 F(x)modr∏i=l(x−ai)。每次把 F(x) 对 r∏i=l(x−ai) 取模即可。这样时间复杂度是 O(nlog2n),但是因为每次递归都要多项式取模所以常数很大。
发现因为余数只有常数项,并且 R(x)=F(x)−Q(x)G(x),所以我们也只用关心 F(x),G(x),Q(x) 的常数项,即 FR(x),GR(x),QR(x) 的 n−1 次项。
所以我们一开始先令 G(x)=n∏i=1(x−ai) 并算出 QR(x),然后分治左区间则乘上右半边的乘积,分治右区间则乘上左半边的乘积。并且注意到递归到 [l,r] 后之后乘的多项式次数 <r−l+1,所以可以只保留后面 r−l+1 项,这样复杂度就对了,还是 O(nlog2n)。
快速插值
考虑拉格朗日插值,答案即为
n∑i=1yi∏j≠ix−xjxi−xj
先考虑每个 i 对应的分母 zi。设 F(x)=n∏i=1(x−xi),相当于要算 F(x)x−xi 代入 xi 后的值。但是此时分子和分母都是 0。根据洛必达法则,此时可以算 F′(x)(x−xi)′=F′(x) 代入 xi 后的值。于是多点求值即可。
再考虑算整个式子。仍然可以分治,分治的时候算 r∑i=lyizi∏l≤j≤r∧j≠i(x−xj)。只需要左边的答案乘上右半边区间多项式的乘积,加上右边的答案乘上左半边区间多项式的乘积即可。时间复杂度 O(nlog2n)。
常系数齐次线性递推
考虑构造矩阵 M,其中 M0,i=ai+1,Mi+1,i=1,其余位置为 0。那么:
⎡⎢
⎢
⎢
⎢
⎢⎣fn+k−1fn+k−2⋮fn⎤⎥
⎥
⎥
⎥
⎥⎦=Mn⎡⎢
⎢
⎢
⎢
⎢⎣fk−1fk−2⋮f0⎤⎥
⎥
⎥
⎥
⎥⎦
M 的特征多项式为 φ(x)=xk−a1xk−1−a2xk−2−⋯−akx0。
设 xn=Q(x)φ(x)+R(x),那么 Mn=Q(M)φ(M)+R(M)。又因为由 Cayley-Hamilton 定理得 φ(M)=0,所以 Mn=R(M)。
设 R(x)=k−1∑i=0rixi,列向量 F=⎡⎢
⎢
⎢
⎢
⎢⎣fk−1fk−2⋮f0⎤⎥
⎥
⎥
⎥
⎥⎦。那么:
Mn=k−1∑i=0riMiMnF=k−1∑i=0ri(MiF)(MnF)k−1=k−1∑i=0ri(MiF)k−1fn=k−1∑i=0rifi
于是剩下的问题是求 R(x),也就是 xnmodφ(x)。直接多项式快速幂即可,每次次数超过 k 了就对 φ(x) 取模。
时间复杂度 O(klogklogn)。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 【杂谈】分布式事务——高大上的无用知识?