前言
最近看到一道经典的题目,就是这一题了。
题意:求 n n n 个点的无向连通图的个数。
题意很简洁,做法也很自然。因为本篇重点不在这一道题,因此这里只做一个简短的说明:
不妨设答案的生成函数为 ∑ i = 1 ∞ f i x i \sum\limits_{i=1}^{\infty} f_ix^i i=1∑∞fixi 。
我们知道我们可以取任意多任意大小的连通块生成一张无向图,而 n n n 个点的无向图个数共有 2 n ( n − 1 ) 2 2^{\frac{n(n-1)} {2}} 22n(n−1) 个。
设 f ( x ) = ∑ i = 1 ∞ f i i ! x i f(x)=\sum\limits_{i=1}^{\infty}\frac{f_i}{i!}x^i f(x)=i=1∑∞i!fixi 。
根据指数型生成函数的知识我们有: e f ( x ) = ∑ i = 0 ∞ 2 i ( i − 1 ) 2 i ! x i e^{f(x)}=\sum\limits_{i=0}^{\infty} \frac{2^{\frac{i(i-1)} {2}}} {i!}x^i ef(x)=i=0∑∞i!22i(i−1)xi
多项式求 ln \ln ln 即可。
正文
显然,联通图可以理解为连通块个数等于 1 1 1 。
如果是连通块个数等于 k k k 的方案数,我们只需要求 f k f^k fk 就可以了,注意到同一张图会被生成 k ! k! k! 次(生成的排列共有 k ! k! k! 种),因此答案的指数型生成函数是 f k k ! \frac{f^k} {k!} k!fk 。
那如果是连通块个数 ≤ k \le k ≤k 的方案数呢?
很显然,把 1 1 1 至 k k k 的函数求和即可(下文为了方便实际上还把函数加了一个常数 1 1 1 ,不过并没有什么影响):
G ( x ) = e x   m o d   x k + 1 G(x)=e^x \bmod x^{k+1} G(x)=exmodxk+1
F ( x ) = G ( f ( x ) ) = ∑ i = 0 k f i ( x ) i ! F(x)=G(f(x))=\sum\limits_{i=0}^{k}\frac{f^i(x)} {i!} F(x)=G(f(x))=i=0∑ki!fi(x)
现在的问题在于如何求 F ( x ) F(x) F(x)。
暴力乘卷积优化的复杂度为 O ( n 2 log n ) O(n^2\log n) O(n2logn) 。
使用快速计算复合函数的算法的话,就是 O ( ( n log n ) 1.5 ) O((n\log n)^{1.5}) O((nlogn)1.5) 。
当然,以上两种做法都没有用到 F F F 的特殊性质。
我们知道 e x e^x ex 的重要特性是导数与原函数相等。
而 G ( f ) = e f   m o d   f k + 1 G(f)=e^f \bmod f^{k+1} G(f)=efmodfk+1
不妨对两边同时求导:
G ′ ( f ) = e f   m o d   f k G'(f)=e^f \bmod f^{k} G′(f)=efmodfk
两式对减:
G ( f ) − G ′ ( f ) = f k k ! G(f)-G'(f)=\frac{f^k} {k!} G(f)−G′(f)=k!fk
用 F F F 替换 G G G :
F ( x ) − F ′ ( x ) f ′ ( x ) = f k ( x ) k ! F(x)-\frac{F'(x)} {f'(x)}=\frac{f^k(x)} {k!} F(x)−f′(x)F′(x)=k!fk(x)
这就是一个很典型的一阶微分方程了。
于是我们有:
F ′ ( x ) − F ( x ) f ′ ( x ) = − f k ( x ) f ′ ( x ) k ! F'(x)-F(x)f'(x)=-\frac{f^k(x)f'(x)} {k!} F′(x)−F(x)f′(x)=−k!fk(x)f′(x)
e − f ( x ) ( F ′ ( x ) − F ( x ) f ′ ( x ) ) = − f k ( x ) f ′ ( x ) e − f ( x ) k ! e^{-f(x)}(F'(x)-F(x)f'(x))=-\frac{f^k(x)f'(x)e^{-f(x)}} {k!} e−f(x)(F′(x)−F(x)f′(x))=−k!fk(x)f′(x)e−f(x)
( F ( x ) e − f ( x ) ) ′ = − f k ( x ) f ′ ( x ) e − f ( x ) k ! (F(x)e^{-f(x)})'=-\frac{f^k(x)f'(x)e^{-f(x)}} {k!} (F(x)e−f(x))′=−k!fk(x)f′(x)e−f(x)
因此有:
F ( x ) = e f ( x ) ∫ − f k ( x ) f ′ ( x ) e − f ( x ) k ! d x F(x)=e^{f(x)}\int -\frac{f^k(x)f'(x)e^{-f(x)}} {k!}dx F(x)=ef(x)∫−k!fk(x)f′(x)e−f(x)dx
这样子就可以在 O ( n log n ) O(n\log n) O(nlogn) 时间内求解了。
个人认为这个解题思路相当巧妙,可以优化许多类似问题。