LG5827 点双连通图计数

点双连通图计数

\(n\) 个点的有标号点双连通图(简单无向图,整个图是一个点双连通分量)的个数,答案对 \(998244353\) 取模。

\(n \leq 10^5\)

题解

https://www.cnblogs.com/bestwyj/p/12063371.html

设有根连通无向图的指数生成函数是 \(F(x)\)。显然有根就在无根的情况下选一个根出来就行了。

点双肯定从点考虑,分析一下一个连通图点双分解的形态,根节点被若干个点双包含。

\(g_i\)\(i\) 个点有根点双图数目。

一个包含根的点双,除了根另有 \(n\) 个点,这 \(n\) 个点都挂着有根连通无向图,可得这一群点的EGF为 \(\sum_{n=1}^\infty g_{n+1} \frac{F(x)^n}{n!}\)

将点双自由排列(这里也可以理解成集合的组合),要选根再乘上一个 \(x\),得到

\[ F(x)=x \exp\left(\sum_{i=1}^\infty g_{i+1} \frac{F(x)^i}{i!}\right) \]

一开始我想的是点双连通分量之间可以看成共用一个点连接起来的

\[ F(x)=\sum_{i=1}^\infty g_i\frac{x^i}{i!}\exp(iF'(x)-i) \]

但这样会算重。因为根节点可能在多个点双中。

\(G(x)=\sum_{i=1}^\infty g_{i+1}\frac{x^i}{i!}\),化简得到

\[ F(x)=x\exp G(F(x)) \]

继续变换得

\[ x=\frac{F(x)}{\exp G(F(x))}\\ \Rightarrow F^{-1}(x)=\frac{x}{\exp G(x)} \]

因此,\(G(x)=\ln \frac{x}{F^{-1}(x)}\),复合逆多项式是不能直接求出来的。

记辅助函数 \(H(x)=\ln \frac{F(x)}{x}\)\(G(x)=H(F^{-1}(x))\)

代入扩展拉格朗日反演:

\[ [x^n]G(x)=\frac{1}{n} [x^{n-1}]H'(x) \left(\frac{x}{F(x)}\right)^n \]

我们要求的即 \(g_n=[x^{n-1}]G(x)\) 可以单次 \(O(n\log n)\) 计算。注意要特判掉 \(n=1\) 的情况。

CO int N=262144;
int omg[2][N],rev[N];
int fac[N],inv[N],ifac[N];

void NTT(poly&a,int dir){
    int lim=a.size(),len=log2(lim);
    for(int i=0;i>1]>>1|(i&1)<<(len-1);
    for(int i=0;i=1;--i) a[i]=mul(a[i-1],inv[i]);
    return a[0]=0,a;
}
poly exp(poly a){
    int n=a.size();
    poly b={1}; // a[0]=0
    if(n==1) return b;
    a.resize(1<<(int)ceil(log2(n)));
    for(int lim=2;lim<2*n;lim<<=1){
        b.resize(lim);poly c=log(b);
        c[0]=add(1+a[0],mod-c[0]);
        for(int i=1;i();
    if(n==1) {puts("1");return;}
    poly f(n+2);
    for(int i=0;i<=n+1;++i) f[i]=mul(fpow(2,(int64)i*(i-1)/2%(mod-1)),ifac[i]);
    f=log(f);
    for(int i=0;i<=n+1;++i) f[i]=mul(f[i],i);
    for(int i=0;i<=n;++i) f[i]=f[i+1];
    f.resize(n+1);
    poly g=f=log(f);
    for(int i=0;i

你可能感兴趣的:(LG5827 点双连通图计数)