多项式基础

多项式基础

Lagrange 插值法

Lagrange 插值 I

给定 n 个点 (xi,yi),求出一个 (n1) 次多项式经过所有的点。

998,422,353 取模。n2×103

我们考虑构造 fi(x) 表示 ji,f(xj)=0,且 f(xi)=yi 的函数。

首先考虑如何满足第一个条件。不难想到只要把 (xxj) 乘起来就行了。也就是

ji(xxj)

然后考虑如何满足第二个条件。将 xi 代入,我们发现此时函数值为 ji(xixj)。那么我们只需要给刚才那个函数乘上 yiji(xixj) 就可以了。

于是我们不难得到了

fi=yijixxjxixj

n 个函数加起来,我们得到

f=i=1nyijixxjxixj

不难发现这个函数符合题意。于是就做完了。

题目要求的是代入一个点求值,可以直接在循环的时候算。

时间复杂度 Θ(n2)

Lagrange 插值 II

本题需要多项式基础。

做法 1:卷积

给定 f(0),f(1)f(n),求 f(m),f(m+1)f(m+n)

n160000

朴素的 Θ(n2) 插值显然无法通过。考虑优化。

注意到本题给的点值很有特点(是 [0,n]Z)。我们将 x+k 代入朴素的插值公式中

f(m+k)=i=0nyijim+kjij

f(m+k)=i=0nyijim+kjjiij

注意下面的 ji(ij) 项,其显然等于

i(i1)(i2)1(1)(2)(in)

(1)nii!(ni)!

预处理后是可以 Θ(1) 求出的。

考虑分子。其显然等于

(m+k)(m+k1)(m+kn)m+ki

(m+k)!(m+ki)(m+kn1)!

于是

f(m+k)=(m+k)!(m+kn1)!i=0n(1)niyi1(m+ki)i!(ni)!

暂时忽略前面的系数,注意到后面的式子有点像卷积的形式,考虑卷积。

考虑利用 cn+k 算出 f(m+k)。那么

cn+k=i=0n+kaibn+ki=i=0naibn+ki+i=n+1n+kaibn+ki=i=0n(1)niyii!(ni)!1(m+ki)!

不难发现当 i[0,n] 时,只需要令

ai=(1)niyii!(ni)!,bi=1(i+mn)!

即可。当 i>n 时,令 ai=0,bi=1(i+mn)! 即可。

时间复杂度 Θ(nlogn)

做法 2:转下降幂

(下降幂的定义在后面)

我们有下降幂的二项式定理

(a+b)n=i=0n(ni)aibni

假设我们已经得到了 f 对应的下降幂多项式,即 f=aixi,现在求 f(x+k)

f(x+k)=i=0nai(x+k)i=i=0naij=0i(ij)xjkij=i=0naij=0ii!j!(ij!)xjkij=i=0naii!j=0ixjj!kij(ij)!=j=0nxjj!i=jnaii!kij(ij)!=j=0nxjj!i=0njai+j(i+j)!kii!

考虑后面的式子如何用卷积求。

卷积的上界是 nj,这意味着我们实际上要取的是卷积后结果的第 nj 项。注意到

cnj=i=0njbnjiai

于是可以令 ai=kii!bnji=ai+j(i+j)!

i=ni,我们得到 bij=ani+j(ni+j)!

再令 i=i+j,我们得到 bi=ani(ni)!

我们可以愉快地做卷积了。

于是,我们

  • 求出 f 的下降幂多项式 F

  • 卷积求出平移后的系数。

  • F 转为普通多项式 f

关于如何将 f 的点值转为下降幂多项式,请参阅本人的多项式基础 blog。

一共要做三次多项式乘法,时间复杂度 Θ(nlogn)

下降幂多项式的特殊插值

也就是,给定 f(0),f(1),,f(n),求出 f=k=0nakxk,使得满足要求。

我们有一个性质:当 k>xxk=0。也就是

f(k)=i=0kaiki=i=0kaik!(ki)!=k!i=0kai1(ki)!

也就是说,hi=f(i)fi=1i!gi=ai 的卷积。

于是我们求出 hf1 即可。

FFT

板子,就不说了。

众所周知,多项式有两种表示,一种是最常用的系数表示,还有点值表示。点值表示的优点是可以非常快速地(Θ(n) 地)做多项式乘法。

但是题目中给出的一般是多项式的系数表示,于是我们要将其转成点值表示。

两个次数为 n 的多项式乘起来之后次数为 2n,所以需要选取 2n+1=Θ(n) 个点。

如果随便选取 Θ(n) 个点代入求值,那么是 Θ(n2) 的。还有优化的空间嘛?

以下设 n,N 均为偶数。

假设我们要选取 N 个点 x1,x2,,xN 代入求值。注意我们可以随便选取这 N 个点。可不可以选择 N2 个特殊的点使得我们只需要算出这 N2 个点的值,我们就可以知道另外 N2 个点的值?

聪明如你肯定想到了。相反数。

如果 f 是偶函数,那么 f(x)=f(x)

如果 f 是奇函数,那么 f(x)=f(x)

但是多项式 f 可以是非奇非偶函数。但是我们可以将它的偶次项和奇次项提出来,得到两个新的函数。

f=i=0naixi=i=0n2a2ix2i+i=0n2a2i+1x2i+1=i=0n2a2ix2i+xi=0n2a2i+1x2i

注意到我们只需要算出左边和右边的两个函数 N2 处的点值,就可以得到全部 N 个点值。

而我们设左边得到一个关于 x2 的函数 g(x2),右边为 h(x2),我们可以得到

f(x)=g(x2)+xh(x2)

f(xi)=g(xi2)+xih(xi2)

f(xi)=g(xi2)xih(xi2)

也就是说,我们只要保证 {xi} 是由相反数两两配对而成的,也就是说,{xi}={x1,x1,x2,x2,,xN2,xN2},我们就能只计算其中的 N2 个点值来得到这所有的 N 个点值。

递归之后我们得到了两个 n21 次多项式。然后你会发现如果这样递归下去,最终是 T(n)=2T(n2)+Θ(n)=Θ(nlogn) 的。但是做完了吗?

如果仔细思考,就会发现一个致命的问题:我们要保证 {xi} 是由相反数两两配对而成的。但是我们递归计算 g 的时候,我们要求的点值变成了 x12,x22,,xN22,显然这不是两两配对的。那我们应该怎么办捏?

显然在 R 内我们已经无法解决这个问题了。于是我们考虑在 C 内解决这个问题。

C 有个特别好的性质:它对开方是封闭的。亦即,xC,yC 使得 y2=x。证明从略。那么我们可以在 C 内去求解(这是多么天才般的想法)!

我们举个例子吧。我们假设我们要求多项式 x3+x2x14 个点值。

我们不妨设起初(第 1 层)的四个点值为 {x1,x1,x2,x2}

于是我们会把 x12x22 分别代入去算。而我们希望在第 2 层中,这两个点也是正负对,即 x12=x22

最后我们需要把 x14=x24 代入去算第 3 层。我们不妨设 x14=x24=1

那么 x12=1,x22=1 是很自然的。

最后我们不难得到 x1=1,x2=i。也就是说,我们只需要算 {1,1,i,i} 处的点值即可。

{1,1,i,i} 是四次单位根 ω4。具体地,如果要求 N 个点的点值,我们可以将其补成 2 的整次幂 N,然后计算 ωN 处的点值即可。

对于 NTT,我们注意到若 Np1,则模数 p 的原根 g 具有和单位根同样良好的性质。于是直接套用即可。

分治 FFT

给定序列 g1n1,求序列 f0n1。其中 fi=j=1ifijgj,边界为 f0=1

Solution 1

朴素地做是 Θ(n2) 的。观察到后面的项依赖前面的项。于是我们可以考虑用 cdq 分治实现。

具体地

  • l=r,结束递归。

  • 递归求解 [l,mid]

  • 计算 [l,mid][mid+1,r] 的影响。

  • 求解 [mid+1,r]

[l,mid]fi,i[mid+1,r] 的影响为 j=lmidfjgij

观察到这是一个卷积的形式。于是我们令 ai=fl+ibi=gi,则计算出 c=ab[l,mid][mid+1,r]i 的贡献为 cil

时间复杂度 Θ(nlog2n)

Solution 2

F(x),g(x)f,g 的生成函数。

F(x)G(x)=i=0+xij+k=ifjgk=F(x)1

F(x)=11G(x)

时间复杂度 Θ(nlogn)

任意模数多项式乘法(MTT)

Method 1:三模 NTT

由于 p109+9n,m105,故最大的数可以到 p2n=1023(默认 n,m 同阶)级,故我们需要选取三个大素数使得 p1p2p3>1023

一般选取 p1=469,762,049p2=998,422,353p3=1,004,535,809,它们都存在原根 G=3。我们求出后可以利用 CRT 求出答案(需要利用 __int128)。

然而有一种不需要利用 __int128 的方法。

{xx1(modA)xx2(modB)xx3(modC)

先合并前两个,那么

x1+k1A=x2+k2B

所以

x1+k1Ax2(modB)

k1x2x1A(modB)

于是我们求出了

xx1+k1A(modAB)

不妨记 x4=x1+k1A。那么

x4+k4AB=x3+k3C

x4+k4ABx3(modC)

k4x3x4AB(modC)

xx4+k4AB(modABC)。又由于 x<ABC,故 x=x4+k4AB

不过这个方法常数很大(需要做 9 次 NTT/INTT)。

Method 2:拆系数 FFT

我们设 c 是一个 p 左右级别的整数。那么我们可以将 F(x) 拆成 A(x)+cB(x)。其中 [xi]A(x)=[xi]F(x)modc[xi]B(x)=[xi]F(x)c。这样可以将系数降到 105 级别。

于是设 F(x)=A(x)+cB(x)G(x)=C(x)+cD(x),于是 F(x)G(x)=A(x)C(x)+c[A(x)D(x)+B(x)C(x)]+c2B(x)D(x)

T(x)=C(x)+D(x)i,其中 i 为虚数单位。于是我们可以在 A(x)T(x) 中找到 A(x)C(x)A(x)D(x),在 B(x)T(x) 中找到 B(x)C(x)B(x)D(x)

于是我们需要:

  • A(x)B(x)T(x) 做 DFT

  • A(x)T(x)B(x)T(x) 做 IDFT

共五次 FFT。常数是三模 NTT 的一半左右。但是这种方法无法通过精心构造的数据。

多项式乘法逆

考虑倍增。假设我们求出了 G0(x) 使得 F(x)G0(x)1(modxn),我们考虑求出 G(x) 使得 F(x)G(x)1(modx2n)

由于 F(x)G(x)1(modx2n),所以必有 F(x)G(x)1(modxn)。于是我们有

F(x)G(x)F(x)G0(x)(modxn)

F(x) 可消去,得到

G(x)G0(x)0(modxn)

G2(x)2G(x)G0(x)+G02(x)0(modx2n)

考虑到 F(x)G(x)1,则两边同乘 F(x)

G(x)2G0(x)+F(x)G02(x)0(modx2n)

G(x)G0(x)(2F(x)G(x))(modx2n)。于是可以倍增求出。

我们有 T(n)=T(n2)+Θ(nlogn),则时间复杂度为 Θ(nlogn)。(但是你猜猜常数有多少?)

任意模数多项式乘法逆

把 NTT 换成任意模数的即可。

多项式除法

给定 f(x)g(x),其中 n=degg<m=degf。求出 q(x),r(x) 满足 f=qg+r,且 degq=degfdeggdegr<degg

好玄学的做法。

1x 代入 f=qg+r,得

f(1x)=q(1x)g(1x)+r(1x)

xnf(1x)=xnmq(1x)xmg(1x)+xnr(1x)

定义 fR(x)=xdegff(1x)。我们可以假装 rm1 次的。

fR=qRgR+xnm+1rR

于是我们在 modxnm+1 意义下可以将 r 忽略掉。

那么在 modxnm+1 意义下求一遍逆元,做一遍多项式乘法和减法即可。

多项式对数函数

G(x)lnF(x)(modxn) 的两边求导,得

G(x)F(x)F(x)(modxn)

于是

G(x)F(x)F(x)(modxn)

时间复杂度 Θ(nlogn)

多项式 Newton 迭代

给定多项式 g(x),若已知 f(x) 满足 g(f(x))=0,求出模 xn 意义下的 f(x)

考虑倍增。

边界是 n=1,此时需要单独解出 [x0]g(f(x))=0 的解。

设已经得到了模 xx2 下的解 f0(x)

g(x)f0(x) 处进行 Taylor 展开,其中 g(i) 表示对 gi 阶导数,规定 g(0)=g

i=0+g(i)(f0(x))i!(f(x)f0(x))i0(modxn)

f(x)f0(x) 最低的非零项系数为 xn2。那么当 i2 时,2n2n,在模 xn 意义下为 0,亦即,i2,都有 (f(x)f0(x))i0(modxn)

那么就很好做了。上式可以化简成

g(f0(x))+g(f0(x))(f(x)f0(x))0(modxn)

于是不难解得

f(x)f0(x)g(f0(x))g(f0(x))(modxn)

那么我们不妨再来回顾一下多项式求逆。

给定 h(x),求出 f(x),使得 h(x)f(x)1(modxn)

观察牛顿迭代的形式

给定多项式 g(x),若已知 f(x) 满足 g(f(x))=0,求出模 xn 意义下的 f(x)

我们要让左边是一个多项式,右边是 0。我们考虑变一下形。

h(x)f(x)1(modxn)

h(x)f(x)10(modxn)

h(x)1f(x)0(modxn)

1f(x)h(x)0(modxn)

那么令 g(f(x))=1f(x)h(x),我们得到

f(x)f0(x)g(f0(x))g(f0(x))(modxn)f0(x)1f0(x)h(x)1f02(x)(modxn)f0(x)(2f0(x)h(x))(modxn)

注意 g(f0(x))主元f0。不妨令 f0=t,则有 g(t)=1th(x),这里 h(x) 当作常数,故 g(t)=1t2

多项式 exp

给定 h(x),求出 f(x) 使得 exp(h(x))f(x)(modxn)

考虑变换形式。上式即

h(x)lnf(x)(modxn)

lnf(x)h(x)0(modxn)。那么令 g(f(x))=lnf(x)h(x)

应用 Newton 迭代的结论,我们得到

f(x)f0(x)g(f0(x))g(f0(x))(modxn)f0(x)lnf(x)h(x)1f0(x)(modxn)f0(x)(1lnf(x)+h(x))(modxn)

T(n)=T(n2)+Θ(nlogn),所以时间复杂度为 Θ(nlogn)。但是常数应该很大。

多项式开根

给定 h(x),求出 f(x) 使得 h(x)f(x)(modxn)

上式即 f2(x)h(x)0(modxn)。于是令 g(f(x))=f2(x)h(x)

f(x)f0(x)g(f0(x))g(f0(x))(modxn)f0(x)f02(x)h(x)2f0(x)(modxn)f02(x)+h(x)2f0(x)(modxn)

T(n)=T(n2)+Θ(nlogn),时间复杂度 Θ(nlogn)。(可能需要求解二次剩余)

多项式快速幂

k10105

事实上,类似整数快速幂的实现可以做到 Θ(nlognlogk)

普通版

普通版保证了 x0=1

Fk(x)=exp(klnF(x))

加强版

首先我们设这个多项式的前 q 项系数为 0,换句话说,i[0,q1][xi]F(x)=0

如果 qkn,那么结果多项式为全 0

否则设 y=[xq]F(x)。我们先给整个多项式乘上 y1,最后还原的时候再乘上 yk

我们把 aq,aq+1,,an1 平移到 a0,a1,,anq1。然后对这个新多项式用套用普通版的方法进行快速幂。

最后乘上 yk,在新多项式前面补上 kq0 即可。

注意,计算 yk 时的 k 是对 (p1) 取模的。而计算 ln 时的 k 是对 p 取模的。

P2767 树的数量

求出包含 n 个节点(无标号)的有根 m 叉树的个数,对 10,007 取模。

两个有根树相同,当且仅当其根节点相同,且从左到右每一棵子树也相同。特别地,两个有根树均为空树,视为两个有根树相同。

n,m127

套路地设 f[n] 为有 n 个节点的有根 m 叉树的数量。显然 f[0]=1

[xn]F=a1+a2+am=n1i=1mfai=[xn1]Fm

那么

F=1+xFm

CF438E The Child and Binary Tree

对于 i[1,m],求出权值为 i 的二叉树的数量,对 998,244,353 取模。

定义二叉树的权值为节点的权值之和。给定大小为 n 的正整数集 C,节点的权值可以从 C 中选取。

两棵二叉树不同当且仅当:

  • 它们的节点数量不同;
  • 或树的形态不同;
  • 或存在一个点的点权不同。

n,m105

套路地设 fi 为权值为 i 的二叉树的数量。显然地,有

fn=cCi=0mfifnic

特别地,f0=1

不妨设 G=gixiF=fixi,其中 gi=[iC]。那么其实就是

fn=k=1mgii=0mfifnik

那么

F=1+i=1mfi

也就是说

F=GF2+1

解得

F=1±14G2G

讨论正确性。

  • + 号的时候,G0F
  • 号的时候,G0F1

因此取 。那么就是

F=114G2G

然后你发现 G 的零次项一定是 0,无法求逆。

但是我们上下同时乘以 1+14G,得到

F=4G2G(1+14G)=21+14G

然后多项式求逆+开根即可。时间复杂度 Θ(mlog2m)

P4389 付公主的背包

i=1n11xvi

要求求出 x1,x2,,xm 的系数。

n,m105

不难想到取 ln,于是化为求

i=1nln(1xvi)

我们有 ln(1x) 的 Taylor 级数:

ln(1x)=i=1+xii

代入就可以得到

ln(1xv)=i=1+xvii

于是问题转化为

i=1nk=1mvixkvik

需要注意的是,不能对于每一个 vi 朴素地直接求和,会被 n1 卡掉。

正确的做法是,求出 i 在数列 v 出现的次数 cnti,然后求

i=1mcntik=1mixkik

最后别忘了 exp 回来。

n,m 视为同阶,时间复杂度 Θ(nlogn)

P7431 [THUPC2017] 小 L 的计算题

给定非负整数数组 a,长度为 n。定义

fk=i=1kaik

对于 i[1,n],求出 fi

n4×105

写出 OGF。设 F(x)=i0fixi

F(x)=i=0+j=1najixi=j=1ni=0+(ajx)i=i=1n11aix

推到这一步,已经可以利用分治 NTT 维护分子和分母,做到 Θ(nlog2n),不过常数是巨大的(反正我的 vector V5 板子 T 了 qaq)。当然,我们有更好的做法。

本文作者:Starrykiller

本文链接:https://www.cnblogs.com/Starrykiller/p/17963608/polynomial-basis

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Starrykiller  阅读(32)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起
  1. 1 404 not found REOL
404 not found - REOL
00:00 / 00:00
An audio error has occurred.