题解 P5828 【边双连通图计数】

iostream

2019-12-18 21:01:26

Solution

## 前置技能:无向连通图计数 设有标号无向图的 egf 为 $F(x)=\sum_{i=0}^\infty \frac{f_ix^i}{i!}$,容易知道 $f_i=2^{n\choose 2}$,则有标号连通无向图的 egf 满足 $G=\ln F$。 ## 边双连通图 首先设有根连通无向图的指数生成函数是 $D(x)$,有根边双连通图的指数生成函数是 $B(x)$。 用 $B$ 来表示 $D$:假设根所在边双大小 $n$,其egf为 $\frac{b_nx^n}{n!}$,而对于其相邻的边,对于其中一条边,它挂着一个连通无向图,接在边双的任意一个点上,所以得到它的egf为 $nD(x)$;若干边自由排列(这里也可以理解成集合的组合),故邻边的egf是 $\exp(nD(x))$。 枚举大小求和得 $$D(x)=\sum_{n\ge 1} \frac{b_nx^n\exp(nD(x))}{n!}=B(x\exp(D(x)))$$ 设 $F(x)=x\exp(D(x))$ 则 $D(x)=B(F(x))$; 两边对 $F(x)$ 作复合逆得 $B(x)=D(F^{-1}(x))$。 有扩展拉格朗日反演公式如下: $$[x^n]A(B^{-1}(x))=\frac{1}{n} [x^{n-1}]A'(x)(\frac{x}{B(x)})^n$$ 代入可得 $[x^n]B(x)=\frac{1}{n} [x^{n-1}]D'(x)(\frac{x}{F(x)})^n$,继续化简可得 $$[x^n]B(x)=\frac{1}{n} [x^{n-1}]D'(x)\exp(-nD(x))$$ 我们可以在 $O(n\log n)$ 的时间复杂度求得 $B(x)$ 的一项系数,注意是有根边双的 egf,最后要乘一个 $n!$ 和除以一个 $n$。 ```cpp //多项式模板略去 void init() { F.resize(n+1); for(int i=0;i<F.size();++i)F[i]=power(2,(ll)i*(i-1)/2%(mod-1),ifac[i]); D=Ln(F); for(int i=0;i<D.size();++i)Mul(D[i],i); G=Deriv(D); } // B(x)->有根边双 // D(x)=B(xexp(D(x))) // [x^n]B(x) = \frac{1}{n}[x^{n-1}]D'(x) (1/exp(D))^n int calc(int n) { Poly C(D.begin(),D.begin()+n),L(G.begin(),G.begin()+n); for(int i=0;i<C.size();++i)Mul(C[i],mod-n); C=Exp(C)*L; return mul(inv[n],C[n-1]); } int main() { init(); scanf("%d",&n); ans=(ll)calc(n)*fac[n-1]%mod; //n!是因为egf, 除去n是因为有根 printf("%d\n",ans); } ```