• cojs DAG计数问题1-4 题解报告


    最近突然有很多人来问我这些题目怎么做OwO

    然而并不是我出的,结论我也不是很懂

    研究了一下觉得非常的一颗赛艇,于是就打算写这样一篇题解

    DAG 1

    我们考虑DAG的性质,枚举出度为0的点

    设出度为0的点有k个,则一共有C(n,k)种方案

    对于剩下的(n-k)个点和这k个点之间可以任意连边,方案为2^(k*(n-k))

    去掉这k个点之后剩下(n-k)个点仍然是DAG,方案为f(n-k)

    则方案数为C(n,k)*2^(k*(n-k))*f(n-k)

    考虑到剩下的(n-k)个点中也可能有出度为0的点,即方案可能会有重复

    考虑算重的部分,用容斥原理解决即可

    最后得到f(n)=sigma((-1)^(k-1)*C(n,k)*2^(k*(n-k))*f(n-k))

    这个递推式是O(n^2)的,可以通过DAG 1

    DAG 2

    不难想到要用FFT来优化上面的递推式

    瓶颈在于2^(k*(n-k))的拆分

    我们发现(n-k)^2=n^2+2nk+k^2

    不难构造出k*(n-k)= n^2/2 - k^2/2 - (n-k)^2/2

    代入之后得到卷积形式,直接做CDQ+FFT即可

    定义g(n)=2^(n^2/2)*n!

    注意到f(n)/g(n)=sigma( (-1)^(k-1)/g(k) * f(n-k)/g(n-k) )

    定义多项式h,h(n)=(-1)^(n-1)/g(n)

    定义多项式ans,ans(n)=f(n)/g(n)

    变形之后得ans-ans*h=1

    之后得到ans=1/(1-h)

    多项式求逆即可

    UPD:注意一下这里的实现,由于n^2/2有可能不是整数,而且(mod-1)和2不是互素的

    但是因为在模意义下我们可以找到x^2=2(mod 998244353)

    所以2^(n^2/2)=x^(n^2)

    至于怎么求解x,因为可以预处理,所以直接枚举算出结果在代码里直接用就可以了

    正常向的做法是用原根取对数之后BSGS搞一搞

    DAG 3

    设f(n)为n个点的DAG的个数(可以不连通)

    设g(n)为n个点的连通DAG的个数

    不难想到用f(n)减去不连通的就是连通的

    计算不连通图常见技巧是枚举特定的某个点所在的联通块的大小

    则得到g(n)=f(n)-sigma( C(n-1,k-1)*g(k)*f(n-k) )

    这样我们就在O(n^2)的时间内求出来了

    DAG 4

    注意到上面的那个式子自然就是卷积形式

    一发CDQ+FFT就可以了

    但是我们可以做到更好

    变形之后得到sigma( g(k)/(k-1)! *f(n-k)/(n-k)! ) = f(n)/(n-1)!

    我们要求g,那么多项式求逆即可

    我们注意到实际上不连通的DAG是由多个连通的DAG组成的

    设可以不连通的DAG的多项式为f,连通DAG的多项式为g

    不难得到f=e^g

    那么g=ln(f)

    多项式求ln即可

  • 相关阅读:
    JavaScript与C# Windows应用程序交互
    用DateTime.ToString(string format)输出不同格式的日期
    时间间隔与暂停
    C#中比较两个时间的时间差
    lambda函数的用法
    Tornado笔记
    DjangoWeb应用开发实战笔记
    再看装饰器
    描述符
    flask简单代码回顾
  • 原文地址:https://www.cnblogs.com/joyouth/p/5682137.html
Copyright © 2020-2023  润新知