废话
大概用了两三个星期来搞多项式和生成函数,人都要被虐傻了qwq……
下面是学到的所有知识的小结,应该是很适合初学者食用的教程,不过一定要按顺序看。
多项式全家桶
学接下来的东西需要的前置知识:微积分的一点初步知识,建议在这里学,看前 4 4 4 集大概就够了?泰勒展开与牛顿迭代,以及关于 e e e 的一些知识。
多项式ln
多项式exp
多项式开根
多项式除法
多项式多点求值
任意模数NTT
在学的过程中同时也在膜拜师兄的优秀板子,所以每一篇的码风不尽相同。
这个是总结出来的自己觉得最好的写法(其实大概就是抄的师兄的代码),也有很多优秀的操作,能够各种优化全家桶的大常数:全家福
生成函数
一些经典套路
这个是最近刚开始补充的,以后大概还会更新。
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)=ex−1,所以贝尔数的生成函数其实就是 e e x − 1 e^{e^x-1} eex−1。
还有一个类似的常用到的地方:设 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∏∞(1−xi1)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} 1−xi1,而 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} 1−xi1 乘起来,分开考虑每一张图就不会有记重的问题了。
看起来这个东西不太能直接求,这个东西是可以优化的,注意到里面那个分式跟付公主的背包里那个很像,令
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∏(1−xi1)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=1∑Filn(1−xi)
两边同时求导,得到:
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=1∑Fi1−xiixi−1
将
−
x
i
-x^i
−xi 看成整体,对
1
1
−
x
i
\dfrac 1 {1-x^i}
1−xi1 泰勒展开一下:
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=1∑Fiixi−1j=0∑xij=i=1∑Fij=0∑ixi(j+1)−1=i=1∑Fij=1∑ixij−1
积分回去:
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=1∑Fij=1∑ijixij=j=1∑j1i=1∑Fixij=j=1∑j1i=1∑Fi(xj)i=j=1∑jF(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=1∑jF(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=0∑nAiBn−iBn=[n=0]=−A01i=1∑nAiBn−i
边界为 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}
An′An+1(n+1)A0Bn+1(n+1)Bn+1=i=0∑nAiBn−i′=i=0∑nAiBn−i+1(n−i+1)=An+1(n+1)−i=1∑nAiBn−i+1(n−i+1)=A0(n+1)An+1(n+1)−∑i=1nAiBn−i+1(n−i+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}
Bn′Bn+1(n+1)Bn+1=i=0∑nBiAn−i′=i=0∑nBiAn−i+1(n−i+1)=n+11i=0∑nBiAn−i+1(n−i+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!}) e≤kA(x)=i=0∑ki!Ai(x)[e≤kA(x)]′=[i=0∑ki!Ai(x)]′=i=0∑ki![Ai(x)]′=i=0∑ki!i×Ai−1(x)×A′(x)=A′(x)×i=0∑k−1i!Ai(x)=A′(x)×(e≤kA(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)=e≤kA(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)Bn′Bn+1=A′(x)×(B(x)−C(x))=i=0∑nAi′×(Bn−i−Cn−i)=n+11i=0∑nAi+1(i+1)×(Bn−i−Cn−i)
由于 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