無標號無根樹計數

EulerEuler變換ε(F(x))=i=1(j=0xij)[xi]F(x)\varepsilon(F(x)) = \sum_{i=1} (\sum_{j=0} x^{ij})^{[x^i]F(x)}
可以用等比數列求和公式+ln\ln+exp\exp求得
ε(F(x))=ei=1F(xi)i\varepsilon(F(x)) = e^{\sum_{i=1} \frac {F(x^i)}{i}}
對於無標號有根樹的生成函數F(x)F(x),可以列出方程:
F(x)=xε(F(x))F(x) = x \varepsilon(F(x))

分治FFTFFT

也即F(x)=xei=1F(xi)iF(x) = xe^{\sum_{i=1}\frac {F(x^i)}{i} }
因爲有exp\exp,所以我們可以對兩邊求導得到:
F(x)=ei=1F(xi)i+xei=1F(xi)i(i=1iF(xi)xi1i)F(x)' = e^{\sum_{i=1} \frac{F(x^i)}i} + xe^{\sum_{i=1} \frac{F(x^i)}i}(\sum_{i=1} \frac{iF'(x^i)x^{i-1}}i)
兩邊同時×x\times x
xF(x)=F(x)+F(x)(i=1F(xi)xi)xF(x)' = F(x) + F(x)(\sum_{i=1} F'(x^i)x^i)
G(x)=F(xi)xiG(x) = F'(x^i)x^i
可以發現[xn]G(x)=dn[xd]F(x)×d[x^n]G(x) = \sum_{d|n} [x^d]F(x) \times d
然後就可以分治FFTFFT了。

牛頓迭代

G(F(x))=F(x)xei=1F(xi)iG(F(x)) = F(x) - xe^{\sum_{i=1}\frac {F(x^i)}i}
考慮計算G(F(x))G(F(x))'
當然也可以求ln\ln
P(x)=ei=2F(xi)iP(x) = e^{\sum_{i=2}\frac {F(x^i)}i}
G(F(x))=lnF(x)lnP(x)F(x)G(F(x)) = \ln F(x) - \ln P(x) - F(x)
G(F(x))=1F(x)P(x)P(x)1=1F(x)1G(F(x))' = \frac 1{F(x)} - \frac {P(x)'}{P(x)} - 1 = \frac 1{F(x)} - 1
是的,P(x)P(x)'就是00,儘管他的表達式裏有F(xi)F(x^i)
注意這裏F(x)F(x)常數項爲00
A(x)=xF(x)A(x) = xF(x)
可以對A(x)A(x)牛頓迭代:
A(x)=A(x)lnA(x)+lnxlnei=2F(xi)ilnxF(x)1A(x)xA(x) = A(x) - \frac {\ln A(x) + \ln x - \ln e^{\sum_{i=2} \frac {F(x^i)}{i}} - \ln x - F(x)}{\frac 1{A(x)} - x}
發現上面的lnx\ln x雖然算不出來,但是他抵消了。

多項式牛頓迭代:

#include<bits/stdc++.h>
#define mod 998244353
#define maxn 550005
#define LL long long
#define rep(i,j,k) for(int i=(j),LIM=(k);i<=LIM;i++)
#define per(i,j,k) for(int i=(j),LIM=(k);i>=LIM;i--)
using namespace std;

int Wl,Wl2,w[maxn],lg[maxn],inv[maxn],fac[maxn],invf[maxn];
int Pow(int b,int k){ int r=1;for(;k;k>>=1,b=1ll*b*b%mod) if(k&1) r=1ll*r*b%mod;return r; }
void init(int n){
	for(Wl=1;n>=Wl<<1;Wl<<=1);int pw=Pow(3,(mod-1)/(Wl2=Wl<<1));
	w[Wl] = 1;
	rep(i,Wl+1,Wl2-1) w[i] = 1ll * w[i-1] * pw % mod;
	per(i,Wl-1,1) w[i] = w[i<<1];
	fac[0] = fac[1] = inv[0] =inv[1] = invf[0] = invf[1] = 1;
	rep(i,2,Wl2) inv[i] = 1ll * (mod - mod / i) * inv[mod % i] % mod , fac[i] = 1ll * fac[i-1] * i % mod,
		invf[i] = 1ll * invf[i-1] * inv[i] % mod , lg[i] = lg[i>>1] + 1;
}
int upd(int x){ return x += x >> 31 & mod; }
void NTT(int *A,int n,int tp){
	static int r[maxn];
	static unsigned long long ar[maxn];
	if(tp^1) reverse(A+1,A+n);
	rep(i,0,n-1) r[i] = r[i>>1]>>1|(i&1)<<lg[n]-1,ar[i]=upd(A[r[i]]);
	for(int L=1;L<n;L<<=1) for(int s=0,L2=L<<1;s<n;s+=L2) for(int k=s,x=L,t;k<s+L;k++,x++)
		t=w[x]*ar[k+L]%mod,ar[k+L]=ar[k]-t+mod,ar[k]+=t;
	rep(i,0,n-1) A[i]=ar[i]%mod;
	if(tp^1) rep(i,0,n-1) A[i] = 1ll * A[i] * inv[n] % mod;
}
void Mul(int *A,int *B,int *C,int n,int m){
	static int st[2][maxn];
	if(1ll * n * m <= 1000){
		rep(i,0,n+m){
			int j=0,L=min(n,i);
			st[0][i] = 0;
			for(;j+7<=L;j+=8)
				st[0][i] = (st[0][i] 
					+ (LL)A[j] * B[i-j]
					+ (LL)A[j+1] * B[i-j-1]
					+ (LL)A[j+2] * B[i-j-2]
					+ (LL)A[j+3] * B[i-j-3]
					+ (LL)A[j+4] * B[i-j-4]
					+ (LL)A[j+5] * B[i-j-5]
					+ (LL)A[j+6] * B[i-j-6]
					+ (LL)A[j+7] * B[i-j-7]
					) % mod;
			for(;j<=L;j++)
				st[0][i] = (st[0][i] + (LL) A[j] * B[i-j]) % mod;
		}
		rep(i,0,n+m) C[i] = st[0][i];
		return;
	}
	int L = 1 << lg[n+m] + 1;
	rep(i,0,L-1) st[0][i] = i <= n ? A[i] : 0,
		st[1][i] = i <= m ? B[i] : 0;
	NTT(st[0],L,1),NTT(st[1],L,1);
	rep(i,0,L-1) C[i] = 1ll * st[0][i] * st[1][i] % mod;
	NTT(C,L,-1);	
}
void Inv(int *A,int *B,int n){
	B[B[1]=0]=Pow(A[0],mod-2);
	static int t[maxn];
	for(int k=2,L=4;k<(n<<1);k<<=1,L<<=1){
		rep(i,0,L-1) t[i]=i<k?A[i]:B[i]=0;
		NTT(t,L,1),NTT(B,L,1);
		rep(i,0,L-1) B[i]=upd(B[i]*(2-1ll*t[i]*B[i]%mod)%mod);
		NTT(B,L,-1);
		rep(i,min(n,k),L-1) B[i] =0;
	}
}

int n,A[maxn];

void Solve(int *A,int n){
	static int st[3][maxn];
	A[0]=1;
	for(int k=2,L=4;k<(n<<1);k<<=1,L<<=1){
		Inv(A,st[0],k);
		rep(i,0,k-1) st[1][i] = A[i+1] * (i+1ll) % mod;
		Mul(st[1],st[0],st[1],k-1,k-1);
		per(i,k-1,1) st[1][i] = 1ll * st[1][i-1] * inv[i] % mod;
		st[1][0] = 0;
		rep(i,1,k-1) for(int j=i,p=0;j<=k;j+=i,p++)
			st[1][j] = (st[1][j] - 1ll * A[p] * inv[i]) % mod;
		st[0][1] --;
		Inv(st[0],st[2],k);
		Mul(st[2],st[1],st[1],k-1,k-1);
		rep(i,0,min(n-1,k-1)) A[i] = upd(A[i] - st[1][i]);
	}
	per(i,n,1) A[i] = A[i-1];
	A[0] = 0;
}

int main(){
	freopen("1.in","r",stdin);
	scanf("%d",&n);
	init(n<<1);
	Solve(A,n+1);
	int ans = A[n];
	rep(i,n/2+1,n-1) ans = (ans - 1ll * A[i] * A[n-i]) % mod;
	if(n%2==0) ans = (ans - 1ll * A[n/2] * (A[n/2] - 1) / 2) % mod;
	printf("%d\n",(ans+mod)%mod);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章