帶標號的DAG計數I IV

2022-04-02 22:03:28 字數 2697 閱讀 4370

帶標號的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 ...