【題解】洛谷 P6295 有標號 DAG 計數【生成函式 多項式】
阿新 • • 發佈:2020-12-17
題意
求有標號弱連通 DAG 的數量。\(n\leq 10^5\)
題解
首先考慮不要求連通時的做法:設 \(i\) 個點時的答案為 \(g_i\),對應的生成函式為 \(F(x)\)。列舉至少有多少個點的入度為 \(0\),選出這些點,決定連邊方式,並乘上容斥係數:
\[g_i=\sum_{j=1}^n \dbinom{i}{j} 2^{j(i-j)} g(i-j) (-1)^{j+1} \]將 \(\dbinom{i}{j}\) 拆成 \(\dfrac{i!}{j!(i-j)!}\),將 \(j(i-j)\) 拆成 \(\dbinom{i}{2}-\dbinom{j}{2}-\dbinom{i-j}{2}\)
\(ln(G)\) 即為連通時的答案。
#include<bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int,int> pii; // 讀優、階乘逆元預處理、多項式板子等略。 // 多項式板子整體架構類似於 EI 的第二代多項式模板(https://blog.csdn.net/EI_Captain/article/details/88628618) int main(){ int n(io); Poly A(zeroes(n)); int p2=1,pp2=1; for(int i=1;i<=n;i++){ pp2=pp2*1ll*p2%mod; (p2&1)?(p2=(p2+mod)>>1):(p2>>=1); A[i]=pp2*1ll*simp.ifac(i)%mod; if(i%2==0)A[i]=mod-A[i]; } Poly G=(Poly(1)-A).inv(); p2=1,pp2=1; for(int i=1;i<=n;i++){ pp2=pp2*1ll*p2%mod; p2=norm(p2<<1); G[i]=G[i]*1ll*pp2%mod; } Poly F=G.ln(); for(int i=1;i<=n;i++){ io.putint(F[i]*1ll*simp.fac(i)%mod%mod,'\n'); } return 0; }