有标号DAG计数(生成函数)

luogu

题解时间

首先考虑暴力,很容易得出 $ f[ i ] = \sum\limits_{ j = 1 }^{ i } ( -1 )^{ j - 1 } \binom{ i }{ j } 2^{ j( i - j ) } f[ i-j ] $ 。

相当于枚举度数为0的节点的个数,向不在这个集合里的点任意连边,之后需要容斥。

考虑如何优化。

$ j(i-j) = \frac{ i^{ 2 } }{ 2 } - \frac{ j^{ 2 } }{ 2 } - \frac{ ( i - j )^{ 2 } }{ 2 } $ 。

$ f[ i ] = \sum\limits_{ j = 1 }^{ i } ( -1 )^{ j - 1 } \frac{ i! }{ j!(i-j)! } \frac{ ( \sqrt{ 2 } )^{ i^{ 2 } } }{ ( \sqrt{ 2 } )^{ j^{ 2 } } ( \sqrt{ 2 } )^{ (i-j)^{ 2 } } } f[ i-j ] $ 。

构造 $ F(x) = \sum\limits_{ i = 0 }^{n} \frac{ f_{ i } }{ i! \sqrt{ 2 }^{ i^{ 2 } } } x^{ i } , G(x) = \sum\limits_{ i = 0 }^{n} \frac{ (-1)^{ i - 1 } }{ i! \sqrt{ 2 }^{ i^{ 2 } } } x^{ i } $ ,

有 $ F( x ) = F( x )G( x ) + 1 $ ,直接求逆。

如果要求图必须是弱连通呢?

直接对EGF取ln就好。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long lint;
namespace RKK
{
const int N=300011,maxn=262144;
const int mo=998244353,G=3,sqrt2=116195171;
lint add(lint a,lint b){return (a+=b)>=mo?a-mo:a;}
lint doadd(lint &a,lint b){if((a+=b)>=mo) a-=mo;}
lint fpow(lint a,lint p){lint ret=1;while(p){if(p&1ll) ret=ret*a%mo;a=a*a%mo;p>>=1;}return ret;}
lint wg[N],iwg[N];int rev[N],lastlen;
inline void init(){for(int i=1;i<maxn;i<<=1) wg[i]=fpow(G,(mo-1)/(i<<1)),iwg[i]=fpow(wg[i],mo-2);}
inline void getrev(int len){for(int i=1;i<len;i++)rev[i]=(rev[i>>1]>>1)|((i&1)*(len>>1));}
inline void ntt(lint *a,int len,int tp)
{
if(lastlen!=len) getrev(len),lastlen=len;
for(int i=0;i<len;i++)if(i<rev[i]) swap(a[i],a[rev[i]]);
for(int i=1;i<len;i<<=1)
{
lint w0=(~tp)?wg[i]:iwg[i];
for(int j=0;j<len;j+=(i<<1))
{
lint w=1;
for(int k=0;k<i;k++,(w*=w0)%=mo)
{
lint w1=a[j+k],w2=w*a[j+k+i]%mo;
a[j+k]=add(w1,w2),a[j+k+i]=add(w1,mo-w2);
}
}
}
lint ilen=fpow(len,mo-2);
if(tp==-1)for(int i=0;i<len;i++) (a[i]*=ilen)%=mo;
}
namespace poly
{
namespace inv
{
lint a[N],b[N];
void work(lint *f,lint *g,int n)
{
g[0]=fpow(f[0],mo-2);
for(int len=1;len<n<<1;len<<=1)
{
memcpy(a,f,len*8),memcpy(b,g,len*8);
ntt(a,len<<1,1),ntt(b,len<<1,1);
for(int i=0;i<len<<1;i++) g[i]=b[i]*(2ll-a[i]*b[i]%mo+mo)%mo;
ntt(g,len<<1,-1),memset(g+len,0,len*8);
}
memset(a,0,n*16),memset(b,0,n*16);
}
}
namespace ln
{
lint a[N],b[N];
void de(lint *f,int n){for(int i=0;i<n;i++) f[i]=f[i+1]*(i+1)%mo;f[n-1]=0;}
void ide(lint *f,int n){for(int i=n-2;i>=0;i--) f[i+1]=f[i]*fpow(i+1,mo-2)%mo;f[0]=0;}
void work(lint *f,lint *g,int n)
{
int len=n;
memcpy(a,f,len*8),de(a,len);
inv::work(f,b,len);
ntt(a,len<<1,1),ntt(b,len<<1,1);
for(int i=0;i<len<<1;i++) g[i]=a[i]*b[i]%mo;
ntt(g,len<<1,-1),ide(g,len);
memset(a,0,len*16),memset(b,0,len*16);
}
}
}
int n;
lint inv[N],fac[N],ifac[N];
void sieve(int n)
{
inv[0]=inv[1]=1;for(int i=2;i<=n;i++) inv[i]=inv[mo%i]*(mo-mo/i)%mo;
fac[0]=1;for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mo;
ifac[0]=1;for(int i=1;i<=n;i++) ifac[i]=ifac[i-1]*inv[i]%mo;
}
lint f[N],g[N],h[N];
int main()
{
scanf("%d",&n);init();
int len=1;while(len<=n) len<<=1;
sieve(len);
g[0]=1;for(int i=1;i<len;i++)
{
g[i]=ifac[i]*fpow(fpow(sqrt2,1ll*i*i%(mo-1)),mo-2)%mo;
if(i&1) g[i]=mo-g[i];
}
poly::inv::work(g,f,len);//求出不保证联通的
for(int i=0;i<len;i++) f[i]=f[i]*fpow(sqrt2,1ll*i*i%(mo-1))%mo;//不乘fac因为还要用egf直接去ln
poly::ln::work(f,h,len);
for(int i=1;i<=n;i++) printf("%lld\n",h[i]*fac[i]%mo);
return 0;
}
}
int main(){return RKK::main();}

有标号DAG计数(生成函数)的更多相关文章

  1. 有标号DAG计数 [容斥原理 子集反演 组合数学 fft]

    有标号DAG计数 题目在COGS上 [HZOI 2015]有标号的DAG计数 I [HZOI 2015] 有标号的DAG计数 II [HZOI 2015]有标号的DAG计数 III I 求n个点的DA ...

  2. P6295 有标号 DAG 计数

    P6295 有标号 DAG 计数 题意 求 \(n\) 个点有标号弱联通 DAG 数量. 推导 设 \(f_i\) 表示 \(i\) 个点有标号 DAG 数量(不保证弱联通),有: \[f(i)=\s ...

  3. 洛谷 P6295 - 有标号 DAG 计数(生成函数+容斥+NTT)

    洛谷题面传送门 看到图计数的题就条件反射地认为是不可做题并点开了题解--实际上这题以我现在的水平还是有可能能独立解决的( 首先连通这个条件有点棘手,我们尝试把它去掉.考虑这题的套路,我们设 \(f_n ...

  4. 题解 有标号DAG计数

    题目传送门 题目大意 给出\(n\),求出对于任意\(t\in[1,n]\),点数为\(t\)的弱联通\(\texttt{DAG}\)个数.答案对\(998244353\)取模. \(n\le 10^ ...

  5. P6295-有标号 DAG 计数【多项式求逆,多项式ln】

    正题 题目链接:https://www.luogu.com.cn/problem/P6295 题目大意 求所有\(n\)个点的弱联通\(DAG\)数量. \(1\leq n\leq 10^5\) 解题 ...

  6. 有标号的DAG计数(FFT)

    有标号的DAG计数系列 有标号的DAG计数I 题意 给定一正整数\(n\),对\(n\)个点有标号的有向无环图(可以不连通)进行计数,输出答案\(mod \ 10007\)的结果.\(n\le 500 ...

  7. COGS2355 【HZOI2015】 有标号的DAG计数 II

    题面 题目描述 给定一正整数n,对n个点有标号的有向无环图(可以不连通)进行计数,输出答案mod 998244353的结果 输入格式 一个正整数n 输出格式 一个数,表示答案 样例输入 3 样例输出 ...

  8. COGS2356 【HZOI2015】有标号的DAG计数 IV

    题面 题目描述 给定一正整数n,对n个点有标号的有向无环图进行计数. 这里加一个限制:此图必须是弱连通图. 输出答案mod 998244353的结果 输入格式 一个正整数n. 输出格式 一个数,表示答 ...

  9. 【题解】有标号的DAG计数4

    [HZOI 2015] 有标号的DAG计数 IV 我们已经知道了\(f_i\)表示不一定需要联通的\(i\)节点的dag方案,考虑合并 参考[题解]P4841 城市规划(指数型母函数+多项式Ln),然 ...

随机推荐

  1. Solution -「ARC 063D」「AT 2149」Snuke's Coloring 2

    \(\mathcal{Decription}\)   Link.   平面上有一个左下角坐标 \((0,0)\) 右上角坐标 \((W,H)\) 的矩形,起初长方形内部被涂白. 现在给定 \(n\) ...

  2. [Java]Java入门笔记(一):IDE设置、部分快捷键

    一.Eclipse 软件设置 注意 同一时间,工作空间只能使用1个. 1.1 创建程序的步骤 创建项目Java Project 注意:项目名不要使用数字,也不要以数字开头: 选择"Use d ...

  3. 日常问题记录 E138: Can't write viminfo file /root/.viminfo!

    问题是因为磁盘不足导致 看磁盘占用情况 排查:du --max-depth=1 -h   这个命令可以查看当前目录下哪个目录占用最大,然后再进一步看

  4. Flash挂马实验

    实验目的 了解Flash木马的原理和危害 实现实验所提到的命令和工具,得到实验结果 实验原理 利用Flash挂马的原理并模拟实现挂马 实验内容 掌握Flash挂马的原理并模拟实现挂马 实验环境描述 1 ...

  5. scrapy爬取youtube游戏模块

    本次使用mac进行爬虫 mac爬虫安装过程中出现诸多问题 避免日后踩坑这里先进行记录 首先要下载xcode ,所以要更新macOS到10.14.xx版本 更新完之后因为等下要进行环境路径配置 但是ma ...

  6. 第六题 Z字走法

    我和答案第一种解法是很相似的  但是时间 和空间都被大部分人击败了. 思路就是用一个标记  为0就竖着走 为1就斜着走 把二维数组填满 我觉得难点在于PHYTON如何创建一个二维数组  而且是不定长的 ...

  7. 案例三:shell统计ip访问情况并分析访问日志

    题目要求 有日志 1.log,部分内容如下: 112.111.12.248 – [25/Sep/2013:16:08:31 +0800]formula-x.haotui.com"/secco ...

  8. 使用Irony开发译码器

    使用Irony开发一个针对G代码的译码器.不想使用Lex&Yacc的原因是: 1.我只会用C#和Python写代码,用Lex&Yacc还得学习新的语法规范,我懒: 2.Lex& ...

  9. selenium+python自动化103-一闪而过的dialog如何定位

    前言 web页面操作的时候经常会遇到一闪而过的 dialog 消息,这些提示语一般只出现了几秒,过后元素节点就会在DOM中消失了. 本篇讲解下用chrome 浏览器如何定位一闪而过的 dialog 消 ...

  10. Qt:手动编辑UI文件——This file can only be edited in Design mode

    UI文件是只读文件,正常情况下我们只能在"Design"模式下,通过调整各种控件的方式间接修改它. 但是有时我们遇到许多重复性的工作,比如向某个Combobox中添加一系列的Ite ...