多项式知识小全+全家桶学习小结

废话

大概用了两三个星期来搞多项式和生成函数,人都要被虐傻了qwq……

下面是学到的所有知识的小结,应该是很适合初学者食用的教程,不过一定要按顺序看。

多项式全家桶

快速傅利叶变换FFT
快速数论变换NTT
多项式求逆

学接下来的东西需要的前置知识:微积分的一点初步知识,建议在这里学,看前 4 4 4 集大概就够了?泰勒展开与牛顿迭代,以及关于 e e e 的一些知识。

多项式ln
多项式exp
多项式开根
多项式除法
多项式多点求值
任意模数NTT

在学的过程中同时也在膜拜师兄的优秀板子,所以每一篇的码风不尽相同。

这个是总结出来的自己觉得最好的写法(其实大概就是抄的师兄的代码),也有很多优秀的操作,能够各种优化全家桶的大常数:全家福

生成函数

OGF
EGF

一些经典套路

这个是最近刚开始补充的,以后大概还会更新。

exp 的组合意义

这个是以后会广泛应用到的很经典的东西,先写出 e f ( x ) e^{f(x)} ef(x) 的泰勒展开形式:
e f ( x ) = 1 + f ( x ) 1 ! + f ( x ) 2 2 ! + f ( x ) 3 3 ! + . . . e^{f(x)}=1+\frac {f(x)} {1!}+\frac {f(x)^2} {2!}+\frac {f(x)^3} {3!}+... ef(x)=1+1!f(x)+2!f(x)2+3!f(x)3+...

[ x i ] f ( x ) [x^i]f(x) [xi]f(x) 表示第 i i i 个元素的种类数,则 f ( x ) i i ! \dfrac {f(x)^i} {i!} i!f(x)i 就表示选出 i i i 个元素,不在乎顺序的方案数。

不在乎顺序是个很优秀的性质,比如说要将一些东西划分为若干个集合,集合之间就是不在乎顺序的。

一个例子是求贝尔数的生成函数,贝尔数即 将 n n n不同的小球划分为若干个集合的方案数。

[ x i ] f ( x ) [x^i]f(x) [xi]f(x) 表示选出一个大小为 i i i 的集合的方案数,若小球是一样的那么 [ x i ] f ( x ) = 1 [x^i]f(x)=1 [xi]f(x)=1,但是这里是不一样的,所以需要考虑标号的问题,容易想到使用 EGF \text{EGF} EGF,即 f ( x ) = x 1 1 ! + x 2 2 ! + x 3 3 ! + . . . f(x)=\dfrac {x^1} {1!}+\dfrac {x^2} {2!}+\dfrac {x^3} {3!}+... f(x)=1!x1+2!x2+3!x3+...

再对 f ( x ) f(x) f(x) exp ⁡ \exp exp 就能得到贝尔数的生成函数了,将每一项乘上 i ! i! i! 就是贝尔数。

容易发现 f ( x ) = e x − 1 f(x)=e^x-1 f(x)=ex1,所以贝尔数的生成函数其实就是 e e x − 1 e^{e^x-1} eex1

还有一个类似的常用到的地方:设 g ( x ) g(x) g(x) 为满足某性质的带标号连通图数量的 EGF \text{EGF} EGF,则 e g ( x ) e^{g(x)} eg(x) 就是满足某性质的带标号图的数量的 EGF \text{EGF} EGF

Euler 变换

先扯一点废话

如果将上面的问题变成:给出 f ( x ) f(x) f(x) 表示满足某性质的无标号连通图数量,如何求满足某性质的连通图数量,那要怎么做呢?

你可能会想:既然这里是无标号的,那么就将 f ( x ) f(x) f(x) OGF \text{OGF} OGF exp ⁡ \exp exp 不就好了吗?

但实际上是不行的。下面的部分属于个人理解,如果说错了还请大方指正qwq

对于无标号图, e f ( x ) e^{f(x)} ef(x) 中第 i i i f ( x ) i i ! \dfrac {f(x)^i} {i!} i!f(x)i,意义为选出 i i i 个连通图的方案数,由于是无序的所以再除以 i ! i! i! 用以去重,但是,如果其中包含两张相同的图,那么就不应该除以 i ! i! i!,而应该是 i ! 2 ! \dfrac {i!} {2!} 2!i!,因为交换这两张图的位置得到的是一样的方案,不应该去重多次。

而在有标号图中,存在一个与标号相关的问题:对于一张由 k k k 个连通图组成的图,假设他们大小分别为 p 1 , p 2 , . . . , p k p_1,p_2,...,p_k p1,p2,...,pk,那么我们计算不同标号方案的式子为 n ! p 1 ! p 2 ! . . . p k ! \dfrac {n!}{p_1!p_2!...p_k!} p1!p2!...pk!n!。但是如果其中存在两张结构相同的连通图,将他们的标号整体交换并没有得到新的方案,所以我们应该也将其除掉。

而这个过程,恰好就在求 e f ( x ) e^{f(x)} ef(x) 时除掉了:注意上面的两个问题的关键点, e f ( x ) e^{f(x)} ef(x) 会除多,当且仅当选出了相同的图,而在有标号图中,恰好也是只有出现相同的图时才需要多除一些,而多除的这部分,正好是 d ! d! d!,即相同图数量,这在两个部分中是相同的,就抵消掉了,于是就能恰好正确计算。

而在 OGF \text{OGF} OGF 中,不存在标号图中少除的部分去和 e f ( x ) e^{f(x)} ef(x) 中多除的部分进行抵消,所以求 exp ⁡ \exp exp 并不能得出正确的解。

正题

F i F_i Fi 表示 F ( x ) F(x) F(x) 的第 i i i 项系数,即 F i = [ x i ] F ( x ) F_i=[x^i]F(x) Fi=[xi]F(x),定义 F ( x ) F(x) F(x) Euler \text{Euler} Euler 变换为:
∏ i = 1 ∞ ( 1 1 − x i ) F i \prod_{i=1}^{\infty} \left(\frac 1 {1-x^i}\right)^{\small{F_i}} i=1(1xi1)Fi

承接上面的无标号图问题,可以认为 F i F_i Fi 表示 i i i 个点的无标号连通图数量,则上面这个求出来的就是无标号图数量。

思想是对每一张连通图造一个 OGF \text{OGF} OGF,一张 i i i 个点的连通图对应的 OGF \text{OGF} OGF 1 1 − x i \dfrac 1 {1-x^i} 1xi1,而 i i i 个点的 OGF \text{OGF} OGF 数量为 F i F_i Fi,于是就将 F i F_i Fi 1 1 − x i \dfrac 1 {1-x^i} 1xi1 乘起来,分开考虑每一张图就不会有记重的问题了。

看起来这个东西不太能直接求,这个东西是可以优化的,注意到里面那个分式跟付公主的背包里那个很像,令 G ( x ) G(x) G(x) F ( x ) F(x) F(x) Euler \text{Euler} Euler 变换,则有:
G ( x ) = ∏ i = 1 ( 1 1 − x i ) F i G(x)=\prod_{i=1} \left(\frac 1 {1-x^i}\right)^{\small {F_i}} G(x)=i=1(1xi1)Fi

两边同时求 ln ⁡ \ln ln,得到:
ln ⁡ G ( x ) = − ∑ i = 1 F i ln ⁡ ( 1 − x i ) \ln G(x)=-\sum_{i=1}F_i\ln(1-x^i) lnG(x)=i=1Filn(1xi)

两边同时求导,得到:
G ′ ( x ) G ( x ) = ∑ i = 1 F i i x i − 1 1 − x i \frac {G'(x)} {G(x)}=\sum_{i=1}F_i\frac {ix^{i-1}} {1-x^i} G(x)G(x)=i=1Fi1xiixi1

− x i -x^i xi 看成整体,对 1 1 − x i \dfrac 1 {1-x^i} 1xi1 泰勒展开一下:
G ′ ( x ) G ( x ) = ∑ i = 1 F i i x i − 1 ∑ j = 0 x i j G ′ ( x ) G ( x ) = ∑ i = 1 F i ∑ j = 0 i x i ( j + 1 ) − 1 G ′ ( x ) G ( x ) = ∑ i = 1 F i ∑ j = 1 i x i j − 1 \begin{aligned} \frac {G'(x)} {G(x)}&=\sum_{i=1}F_iix^{i-1}\sum_{j=0}x^{ij}\\ \frac {G'(x)} {G(x)}&=\sum_{i=1}F_i\sum_{j=0}ix^{i(j+1)-1}\\ \frac {G'(x)} {G(x)}&=\sum_{i=1}F_i\sum_{j=1}ix^{ij-1} \end{aligned} G(x)G(x)G(x)G(x)G(x)G(x)=i=1Fiixi1j=0xij=i=1Fij=0ixi(j+1)1=i=1Fij=1ixij1

积分回去:
ln ⁡ G ( x ) = ∑ i = 1 F i ∑ j = 1 i x i j i j ln ⁡ G ( x ) = ∑ j = 1 1 j ∑ i = 1 F i x i j ln ⁡ G ( x ) = ∑ j = 1 1 j ∑ i = 1 F i ( x j ) i ln ⁡ G ( x ) = ∑ j = 1 F ( x j ) j \begin{aligned} \ln G(x)&=\sum_{i=1}F_i\sum_{j=1}\frac {ix^{ij}} {ij}\\ \ln G(x)&=\sum_{j=1}\frac 1 j\sum_{i=1}F_ix^{ij}\\ \ln G(x)&=\sum_{j=1}\frac 1 j\sum_{i=1}F_i(x^j)^i\\ \ln G(x)&=\sum_{j=1}\frac {F(x^j)} j\\ \end{aligned} lnG(x)lnG(x)lnG(x)lnG(x)=i=1Fij=1ijixij=j=1j1i=1Fixij=j=1j1i=1Fi(xj)i=j=1jF(xj)

exp ⁡ \exp exp 回去:
G ( x ) = exp ⁡ ( ∑ j = 1 F ( x j ) j ) G(x)=\exp\left(\sum_{j=1}\frac {F(x^j)} j\right) G(x)=exp(j=1jF(xj))

各种 n 2 n^2 n2 递推

为了方便,约定 F i F_i Fi 表示多项式 F ( x ) F(x) F(x) x i x^i xi 项的系数。

下面这些是当你不想码或没必要码全家桶时使用的递推技巧,但是都是 O ( n 2 ) O(n^2) O(n2) 的,而全家桶板子是 O ( 大常数 × n log ⁡ n ) O(大常数\times n\log n) O(大常数×nlogn) 的,如果 n n n 十分小以至于跟大常数差不多一个级别,或者在代码中的其他地方已经有 O ( n 2 ) O(n^2) O(n2) 复杂度的地方了,那么就可以使用递推而不需要码全家桶。

逆元

B ( x ) B(x) B(x) A ( x ) A(x) A(x) 的逆元,即满足 A ( x ) B ( x ) = 1 A(x)B(x)=1 A(x)B(x)=1,那么有:
∑ i = 0 n A i B n − i = [ n = 0 ] B n = − 1 A 0 ∑ i = 1 n A i B n − i \begin{aligned} \sum_{i=0}^n A_i B_{n-i}&=[n=0]\\ B_n&=-\frac 1 {A_0}\sum_{i=1}^n A_i B_{n-i}\\ \end{aligned} i=0nAiBniBn=[n=0]=A01i=1nAiBni

边界为 B 0 = i n v ( A 0 ) B_0=inv(A_0) B0=inv(A0)

ln

[ ln ⁡ A ( x ) ] ′ = A ′ ( x ) A ( x ) ln ⁡ A ( x ) = ∫ A ′ ( x ) A ( x ) \begin{aligned} [\ln A(x)]'&=\frac {A'(x)} {A(x)}\\ \ln A(x)&=\int \frac {A'(x)} {A(x)} \end{aligned} [lnA(x)]lnA(x)=A(x)A(x)=A(x)A(x)

B ( x ) = ln ⁡ A ( x ) B(x)=\ln A(x) B(x)=lnA(x),那么有 B ′ ( x ) = A ′ ( x ) A ( x ) B'(x)=\dfrac {A'(x)} {A(x)} B(x)=A(x)A(x),即 A ( x ) × B ′ ( x ) = A ′ ( x ) A(x)\times B'(x)=A'(x) A(x)×B(x)=A(x),那么有:
A n ′ = ∑ i = 0 n A i B n − i ′ A n + 1 ( n + 1 ) = ∑ i = 0 n A i B n − i + 1 ( n − i + 1 ) A 0 B n + 1 ( n + 1 ) = A n + 1 ( n + 1 ) − ∑ i = 1 n A i B n − i + 1 ( n − i + 1 ) B n + 1 = A n + 1 ( n + 1 ) − ∑ i = 1 n A i B n − i + 1 ( n − i + 1 ) A 0 ( n + 1 ) \begin{aligned} A'_n&=\sum_{i=0}^n A_i B'_{n-i}\\ A_{n+1}(n+1)&=\sum_{i=0}^n A_i B_{n-i+1}(n-i+1)\\ A_0 B_{n+1}(n+1)&=A_{n+1}(n+1)-\sum_{i=1}^n A_iB_{n-i+1}(n-i+1)\\ B_{n+1}&=\frac {A_{n+1}(n+1)-\sum_{i=1}^n A_iB_{n-i+1}(n-i+1)} {A_0 (n+1)} \end{aligned} AnAn+1(n+1)A0Bn+1(n+1)Bn+1=i=0nAiBni=i=0nAiBni+1(ni+1)=An+1(n+1)i=1nAiBni+1(ni+1)=A0(n+1)An+1(n+1)i=1nAiBni+1(ni+1)

exp

[ e A ( x ) ] ′ = e A ( x ) A ′ ( x ) [e^{A(x)}]'=e^{A(x)} A'(x) [eA(x)]=eA(x)A(x)

B ( x ) = e A ( x ) B(x)=e^{A(x)} B(x)=eA(x),那么有:
B n ′ = ∑ i = 0 n B i A n − i ′ B n + 1 ( n + 1 ) = ∑ i = 0 n B i A n − i + 1 ( n − i + 1 ) B n + 1 = 1 n + 1 ∑ i = 0 n B i A n − i + 1 ( n − i + 1 ) \begin{aligned} B'_n&=\sum_{i=0}^n B_i A'_{n-i}\\ B_{n+1}(n+1)&=\sum_{i=0}^n B_i A_{n-i+1} (n-i+1)\\ B_{n+1}&=\frac 1 {n+1}\sum_{i=0}^n B_i A_{n-i+1} (n-i+1) \end{aligned} BnBn+1(n+1)Bn+1=i=0nBiAni=i=0nBiAni+1(ni+1)=n+11i=0nBiAni+1(ni+1)

同样的,做 exp ⁡ \exp exp 要求 A 0 = 0 A_0=0 A0=0,所以边界为 B 0 = 1 B_0=1 B0=1

k_exp

e ≤ k A ( x ) = ∑ i = 0 k A i ( x ) i ! [ e ≤ k A ( x ) ] ′ = [ ∑ i = 0 k A i ( x ) i ! ] ′ = ∑ i = 0 k [ A i ( x ) ] ′ i ! = ∑ i = 0 k i × A i − 1 ( x ) × A ′ ( x ) i ! = A ′ ( x ) × ∑ i = 0 k − 1 A i ( x ) i ! = A ′ ( x ) × ( e ≤ k A ( x ) − A k k ! ) e^{A(x)}_{\leq k}=\sum_{i=0}^k \frac {A^i(x)} {i!}\\ [e^{A(x)}_{\leq k}]'=[\sum_{i=0}^k \frac {A^i(x)} {i!}]'=\sum_{i=0}^k \frac {[A^i(x)]'} {i!}=\sum_{i=0}^k \frac {i\times A^{i-1}(x)\times A'(x)} {i!}\\ =A'(x)\times \sum_{i=0}^{k-1} \frac {A^i(x)} {i!}=A'(x)\times(e^{A(x)}_{\leq k}-\frac {A^k} {k!}) ekA(x)=i=0ki!Ai(x)[ekA(x)]=[i=0ki!Ai(x)]=i=0ki![Ai(x)]=i=0ki!i×Ai1(x)×A(x)=A(x)×i=0k1i!Ai(x)=A(x)×(ekA(x)k!Ak)

B ( x ) = e ≤ k A ( x ) , C ( x ) = A k k ! B(x)=e^{A(x)}_{\leq k},C(x)=\dfrac {A^k} {k!} B(x)=ekA(x),C(x)=k!Ak C C C 可以用多项式快速幂求出,那么有:
B ′ ( x ) = A ′ ( x ) × ( B ( x ) − C ( x ) ) B n ′ = ∑ i = 0 n A i ′ × ( B n − i − C n − i ) B n + 1 = 1 n + 1 ∑ i = 0 n A i + 1 ( i + 1 ) × ( B n − i − C n − i ) \begin{aligned} B'(x)&=A'(x)\times (B(x)-C(x))\\ B'_n&=\sum_{i=0}^n A'_i\times (B_{n-i}-C_{n-i})\\ B_{n+1}&=\frac 1 {n+1} \sum_{i=0}^n A_{i+1}(i+1)\times (B_{n-i}-C_{n-i})\\ \end{aligned} B(x)BnBn+1=A(x)×(B(x)C(x))=i=0nAi×(BniCni)=n+11i=0nAi+1(i+1)×(BniCni)

由于 B B B 的常数项被导掉了,所以需要手动求: B 0 = ∑ i = 0 k A 0 i i ! B_0=\sum_{i=0}^k \dfrac{A_0^i} {i!} B0=i=0ki!A0i

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值