• 【题解】洛谷 P6295 有标号 DAG 计数【生成函数 多项式】


    题目链接

    题意

    求有标号弱连通 DAG 的数量。(nleq 10^5)

    题解

    首先考虑不要求连通时的做法:设 (i) 个点时的答案为 (g_i),对应的生成函数为 (F(x))。枚举至少有多少个点的入度为 (0),选出这些点,决定连边方式,并乘上容斥系数:

    [g_i=sum_{j=1}^n dbinom{i}{j} 2^{j(i-j)} g(i-j) (-1)^{j+1} ]

    (dbinom{i}{j}) 拆成 (dfrac{i!}{j!(i-j)!}),将 (j(i-j)) 拆成 (dbinom{i}{2}-dbinom{j}{2}-dbinom{i-j}{2}),上式显然是一个卷积,可以写作 (G=Gcdot A+1),解出 (G)

    (ln(G)) 即为连通时的答案。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    typedef pair<int,int> pii;
    
    // 读优、阶乘逆元预处理、多项式板子等略。
    // 多项式板子整体架构类似于 EI 的第二代多项式模板(https://blog.csdn.net/EI_Captain/article/details/88628618)
    
    int main(){
        int n(io);
        Poly A(zeroes(n));
        int p2=1,pp2=1;
        for(int i=1;i<=n;i++){
            pp2=pp2*1ll*p2%mod;
            (p2&1)?(p2=(p2+mod)>>1):(p2>>=1);
            A[i]=pp2*1ll*simp.ifac(i)%mod;
            if(i%2==0)A[i]=mod-A[i];
        }
        Poly G=(Poly(1)-A).inv();
        p2=1,pp2=1;
        for(int i=1;i<=n;i++){
            pp2=pp2*1ll*p2%mod;
            p2=norm(p2<<1);
            G[i]=G[i]*1ll*pp2%mod;
        }
        Poly F=G.ln();
        for(int i=1;i<=n;i++){
            io.putint(F[i]*1ll*simp.fac(i)%mod%mod,'
    ');
        }
        return 0;
    }
    
    知识共享许可协议
    若文章内无特别说明,公开文章采用知识共享署名-相同方式共享 4.0 国际许可协议进行许可。
  • 相关阅读:
    基于组的策略(GBP)开启新型网络设计时代
    49 多维数组(二维数组)
    48 查找
    47 排序
    46 字符数组和字符串
    45 数组应用
    44 数组
    43 C语言宏定义
    42 预处理命令
    41 函数封装练习
  • 原文地址:https://www.cnblogs.com/wallbreaker5th/p/14151445.html
Copyright © 2020-2023  润新知