有标号DAG计数(生成函数)
有标号DAG计数(生成函数)
题解时间
首先考虑暴力,很容易得出 $ 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计数(生成函数)的更多相关文章
- 有标号DAG计数 [容斥原理 子集反演 组合数学 fft]
有标号DAG计数 题目在COGS上 [HZOI 2015]有标号的DAG计数 I [HZOI 2015] 有标号的DAG计数 II [HZOI 2015]有标号的DAG计数 III I 求n个点的DA ...
- P6295 有标号 DAG 计数
P6295 有标号 DAG 计数 题意 求 \(n\) 个点有标号弱联通 DAG 数量. 推导 设 \(f_i\) 表示 \(i\) 个点有标号 DAG 数量(不保证弱联通),有: \[f(i)=\s ...
- 洛谷 P6295 - 有标号 DAG 计数(生成函数+容斥+NTT)
洛谷题面传送门 看到图计数的题就条件反射地认为是不可做题并点开了题解--实际上这题以我现在的水平还是有可能能独立解决的( 首先连通这个条件有点棘手,我们尝试把它去掉.考虑这题的套路,我们设 \(f_n ...
- 题解 有标号DAG计数
题目传送门 题目大意 给出\(n\),求出对于任意\(t\in[1,n]\),点数为\(t\)的弱联通\(\texttt{DAG}\)个数.答案对\(998244353\)取模. \(n\le 10^ ...
- P6295-有标号 DAG 计数【多项式求逆,多项式ln】
正题 题目链接:https://www.luogu.com.cn/problem/P6295 题目大意 求所有\(n\)个点的弱联通\(DAG\)数量. \(1\leq n\leq 10^5\) 解题 ...
- 有标号的DAG计数(FFT)
有标号的DAG计数系列 有标号的DAG计数I 题意 给定一正整数\(n\),对\(n\)个点有标号的有向无环图(可以不连通)进行计数,输出答案\(mod \ 10007\)的结果.\(n\le 500 ...
- COGS2355 【HZOI2015】 有标号的DAG计数 II
题面 题目描述 给定一正整数n,对n个点有标号的有向无环图(可以不连通)进行计数,输出答案mod 998244353的结果 输入格式 一个正整数n 输出格式 一个数,表示答案 样例输入 3 样例输出 ...
- COGS2356 【HZOI2015】有标号的DAG计数 IV
题面 题目描述 给定一正整数n,对n个点有标号的有向无环图进行计数. 这里加一个限制:此图必须是弱连通图. 输出答案mod 998244353的结果 输入格式 一个正整数n. 输出格式 一个数,表示答 ...
- 【题解】有标号的DAG计数4
[HZOI 2015] 有标号的DAG计数 IV 我们已经知道了\(f_i\)表示不一定需要联通的\(i\)节点的dag方案,考虑合并 参考[题解]P4841 城市规划(指数型母函数+多项式Ln),然 ...
随机推荐
- Solution -「ARC 063D」「AT 2149」Snuke's Coloring 2
\(\mathcal{Decription}\) Link. 平面上有一个左下角坐标 \((0,0)\) 右上角坐标 \((W,H)\) 的矩形,起初长方形内部被涂白. 现在给定 \(n\) ...
- python 定时任务apscheduler的使用
apscheduler 的使用 我们项目中总是避免不了要使用一些定时任务,比如说最近的项目,用户点击报名考试以后需要在考试日期临近的时候推送小程序消息提醒到客户微信上,翻了翻 fastapi 中的 ...
- CentOS 7 升级 gcc-4.8.5 到 gcc-5.4.0
文章目录 1.环境介绍 2.下载gcc-5.4.0源码包 3.编译安装gcc 4.验证gcc版本 5.更新gcc连接 1.环境介绍 [root@localhost ~]# gcc -v Using b ...
- 通过shell脚本统计elasticsearch indices每天的数量以及大小
前情提要: 最近elasticsearch集群总出问题,之前虽然修复了,现在又出现新的问题,于是PM要求拉取elasticsearch每天建立的索引有多少,索引有多大,需要对机器进行评估 客户现场无法 ...
- java中的interface(接口)
概念 usb插槽就是现实中的一个接口 你可以把u盘都插在usb插槽上,而不用担心买来的u盘插不进插槽中不管是插电脑,还是插相机,还是插收音机原因是做usb的厂家和做各种设备的厂家都遵守了统一的规定包括 ...
- logstash根据日志关键词报警
logstash是可以根据日志级别,日志类型进行报警通知的. 这次精简教程,排除filebeat自带的#include_lines: ['^ERR', '^WARN']写法,直接使用logstash报 ...
- RENIX报文两个字段嵌套变化——网络测试仪实操
RENIX软件如何实现报文中两个字段嵌套变化,以下为您实操讲解详细步骤. 1.打开Renix软件,连接机框并预约测试端口: 2.创建一条RAW流量(Binding流量也可以,这里用RAW流做例子) 3 ...
- 【缓存】CPU高速缓存 之MESI 性协议 Gif 动画
CPU缓存架构 不同的CPU厂商的架构也有些不同,在这里只介绍流行的缓存架构 缓存一致性可以分为三个点: 在进程每个写入运算时都立刻采取措施保证资料一致性 每个独立的运算,假如它造成资料值的改变,所有 ...
- Iptables 防火墙常用配置
转至:https://blog.csdn.net/lswzw/article/details/87971259 Iptables 防火墙常用配置 概念 命令行模式 查看 & 命令 -n:直接显 ...
- Qt:如何生成可执行文件
参考 (18条消息) QT5的程序打包发布(将QT5的工程项目打包成一个exe程序)_kslly的专栏-CSDN博客 环境配置 Windows 10系统 MSVC 2017编译器 工具 Qt 5自带的 ...