集合冪級數的\(\ln,\exp\)
起始:求聯通子圖個數
令\(F(x)\)為聯通的生成子圖個數的形式冪級數,可以簡單求出\(G(x)\)為生成子圖個數的形式冪級數
下可能略寫\(F(x)\)為\(F\)
不連通的子圖可以通過聯通子圖做集合並運算得到,即構造卷積
\(\begin{aligned} F\times G=\sum_{S\ne \empty}\sum_{T\ne \empty,S\cap T=\empty} [x^S]F\cdot [x^T]G\cdot x^{S\cup T} \end{aligned}\)
顯然滿足關系式\(\begin{aligned} G=\sum_{i\ge 1} \frac{F^i}{i!}=e^{F}-1\end{aligned}\)
\(F=\ln (G+1)\)
計算集合冪級數\(\ln\)的方法似乎非常抽象
方法是:
1.類似子集卷積,把所有項按照占位數(集合包含元素個數)分開,記錄在第二維
2.求出\(\text{FMT}\)
3.對於集合冪級數每一位(現在是一個形式冪級數)求出其\(\ln\)的前\(n\)項
4.求出\(\text{IFMT}\)
求出形式冪級數\(\ln\)的\(n^2\)方法是
\(F=\ln (G+1)\)
\(F'=\frac{G'}{G+1}\)
\(F'(G+1)=G'\)
\(\begin{aligned}F'_i=G'_i-\sum_{j=1}G_jF'_{i-j}\end{aligned}\)
類似的,可以計算集合冪級數的\(\exp\),即由上面的\(F\)求\(G\)
\(\begin{aligned}G'_i=F'_i+\sum_{j=1}G_jF'_{i-j}\end{aligned}\)
可能在子圖計數題中出現
下面是代碼實現上的參考
#define Mod1(x) ((x>=P)&&(x-=P))
#define Mod2(x) ((x<0)&&(x+=P))
#define rep(i,a,b) for(int i=a;i<=b;++i)
int I[N];// 模逆元
void FMT(int F[M][N],int f){
for(int i=1;i<m;i<<=1) for(int l=0;l<m;l+=i*2)
for(int j=l;j<l+i;++j) if(f==1) rep(d,1,n) F[j+i][d]+=F[j][d],Mod1(F[j+i][d]);
else rep(d,1,n) F[j+i][d]-=F[j][d],Mod2(F[j+i][d]);
}
void Ln(int *a){
static int b[N];
rep(i,0,n-1) {
int t=0;
rep(j,0,i-1) t=(t+1ll*b[j]*a[i-j])%P;
b[i]=(1ll*a[i+1]*(i+1)-t+P)%P;
}
rep(i,1,n) a[i]=1ll*b[i-1]*I[i]%P;
}
void Exp(int *a){
static int b[N];
rep(i,0,n-1) b[i]=1ll*a[i+1]*(i+1)%P;
rep(i,0,n-1) {
int t=b[i];
rep(j,1,i) t=(t+1ll*a[j]*b[i-j])%P;
a[i+1]=1ll*t*I[i+1]%P;
}
}
void Ln(int F[M][N]) {
FMT(F,1);
rep(i,1,m-1) Ln(F[i]);
FMT(F,-1);
}
void Exp(int F[M][N]) {
FMT(F,1);
rep(i,1,m-1) Exp(F[i]);
FMT(F,-1);
}