帶標號的dag計數,陳指導最近出了一道最基礎的,發現好久沒用過生成函式那一類的了就來看看
dag的定義相信都不同多說了,以下預設對\(998244353\)取模
pro:求\(n\)點帶標號的dag的數目,不強制聯通,\(n\le 5000\)
sol:顯然考慮\(o(n^2)\),設\(f_i\)表示答案,我們每次列舉dag中入度為\(0\)的點的數目\(j\)
此時圖被拆成了兩個部分,前面的\(j\)個點只能向後面的\(i-j\)個點連邊,而後面的\(i-j\)個點可以隨便連
但我們仔細一想後面的點隨便連並不保證入度為\(0\)的點只有前面的\(j\)個,因此要容斥一下:
\[f_i=\sum_^i (-1)^\times c_i^j\times 2^\times f_
\]
#include#define ri register int
#define ci cosnt int&
using namespace std;
const int n=5005,mod=998244353;
int n,c[n][n],f[n],pw[n*n];
int main()
return printf("%d",f[n]),0;
}
pro:求\(n\)點帶標號的dag的數目,不強制聯通,\(n\le 100000\)
sol:顯然考慮化式子然後用多項式來做,我們發現這個式子中有乙個\(j(i-j)\)的項涉及了\(ij\),顯然我們要想辦法把它拆成可以獨立算的
\[j(i-j)=\frac-\frac-\frac
\]由於\(2\)在模\(998244353\)意義下存在二次剩餘,然後再拆一下組合數移個項:
\[\frac}=\sum_^i \frac}}\times \frac}}
\]顯然令\(f(x)=\sum_^n \frac} x^i,g(x)=\sum_^n\frac}} x^i\)
則有\(f(x)=g(x)f(x)+1\),故\(f(x)=\frac\)
多項式求逆即可,複雜度\(o(n\log n)\)
#include#include#define ri register int
#define ci const int&
using namespace std;
const int n=100005,mod=998244353,r2=882049182;
int n,fact[n],invf[n],f[n<<2],g[n<<2],ir2;
inline int quick_pow(int x,int p=mod-2,int mul=1)
inline int sum(ci x,ci y)
inline int sub(ci x,ci y)
inline void init(ci n)
namespace poly
^ c_^j\times f_j\times g_
\]#include#define ri register int
#define ci cosnt int&
using namespace std;
const int n=5005,mod=998244353;
int n,c[n][n],f[n],g[n],pw[n*n];
int main()
for (i=1;i<=n;++i) for (g[i]=f[i],j=1;jpro:求\(n\)點帶標號的dag的數目,要求弱聯通,\(n\le 100000\)
sol:同上化一化式子,容易得到:
\[\frac=\frac-\sum_^ \frac\times \frac}
\]設\(f(x)=\sum_^n \frac x^i,g(x)=\sum_^n \frac x^i,h(x)=\sum_^n \frac x^i\)
則有\(g(x)=h(x)-f(x)g(x)\),故\(g(x)=\frac\)
再次上多項式求逆即可,複雜度\(o(n\log n)\)
ps:還有一種看起來很優美的指數型生成函式並利用多項式求$\ln $的做法,可惜我策不懂的說
#include#include#define ri register int
#define ci const int&
using namespace std;
const int n=100005,mod=998244353,r2=882049182;
int n,fact[n],invf[n],f[n<<2],g[n<<2],h[n<<2],t[n<<2],ir2,lim;
inline int quick_pow(int x,int p=mod-2,int mul=1)
inline int sum(ci x,ci y)
inline int sub(ci x,ci y)
inline void init(ci n)
namespace poly
{ int b[n<<2],rev[n<<2],lim,p;
inline void ntt(int *f,ci opt)
{ ri i,j,k; for (i=0;i>1]>>1)|((i&1)<>1),init(n<<1),i=0;i數數題真是有趣呢
有標號的DAG計數I IV
最近心血來潮來寫一寫這個玩意兒。請特別注意定義生成函式時下標的起始位置。求 n 點帶標號 dag 的數量模 10007 n le5000 資料範圍顯然 o n 2 設 f i 表示答案,列舉 dag 中入度為零的點的數量 j 方案數為 binom ij 將圖拆成兩個部分,前 j 個點向後 i j 個...
有標號的DAG計數 II
給定一正整數n,對n個點有標號的有向無環圖 可以不連通 進行計數,輸出答案mod 998244353的結果 考慮 o n 2 dp 列舉出度為 0 的點,構成的新 dag 方案數為 f i f i 1 c 2 即從 n 個點中選出乙個點,作為出度為 0 的點,然後剩下 n 1 個點向這個點任意連邊 ...
有標號DAG計數 生成函式
luogu 首先考慮暴力,很容易得出 f i sum limits 1 binom 2 f i j 相當於列舉度數為0的節點的個數,向不在這個集合裡的點任意連邊,之後需要容斥。考慮如何優化。j i j frac frac frac f i sum limits 1 frac frac sqrt f ...