有标号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. 我的平安夜-Merry Christmas

    我的平安夜-Merry Christmas 平安夜给自己买的第一个"苹果",嘻嘻. 今夜,不想去学习技术知识点什么的, 我们就想到哪里写哪里,就简单聊聊思维方式吧. 其实我不想做今 ...

  2. SpringBoot2.x设置文件上传文件的大小

    The field file exceeds its maximum permitted size of 1048576 bytes spring: # 设置文件上传文件大小 servlet: mul ...

  3. Java超全大纲.jpg

    Java超全大纲.jpg

  4. Python 随机(random)模块的不可预测之美

    1 . 概念 1.1 真.伪随机数 大部分的计算机语言都会提供 API 生成随机数,此类 API 称为随机数生成器. 计算机可以用随机数模拟现实世界中的各种随机概率问题,没有随机生成器的编程语言不是& ...

  5. Wireshark教程之高级功能

    实验目的 1.工具介绍 2.主要应用 实验原理 1.网络管理员用来解决网络问题 2.网络安全工程师用来检测安全隐患 3.开发人员用来测试执行情况 4.学习网络协议 实验内容 1.数据流追踪功能 2.协 ...

  6. centos7云服务器安装nginx记录

    nginx作为一个web和反向服务器,应用广泛,尤其适合学习c/c++的人进行使用学习,今天就对这个我听了很多的nginx进行了一次安装配置,主要是针对菜鸟教程中的安装引导进行的个人试验.主要的关注点 ...

  7. BI报表系统该如何集成到其他系统呢?

    近期小麦我经常收到很多用户的反馈,想知道Smartbi的报表能不能从微信/钉钉之类的直接跳转到已做好的报表页面?他们都希望通过这种方式尽可能地避免由于各个管理软件账号密码不同而造成的不便,能够在日常工 ...

  8. 如何在shell脚本里使用sftp批量传送文件(二)

    原文链接:http://bbs.chinaunix.net/archiver/tid-508290.html 主要步骤如下: 1.为运行shell脚本的本地用户生成密钥对2.将其中的公钥分发到sftp ...

  9. SpringMVC教程--eclipse中使用maven创建springMVC项目

    一.在eclipse中创建maven-archetype-webapp项目: 1.新建项目选择maven项目 2.默认,下一步 3.选择maven-archetype-webapp,其他保持默认即可 ...

  10. ACM训练,大理石在哪儿?

    int p = lower_bound(a, a+num, x) - a; //在已排序数组a中查找大于或等于x的第一个位置 lower_bound( )返回的是一个迭代器,-a相当于减去a的首地址, ...