[LOJ Chen 6363] "rose under the ground" (polynomial fast power / extended Lagrangian inversion)

Portal

Lagrangian inversion:
If f(g(x))=xf(g(x))=xf(g(x))=x
Then g(f(x))=x, and [x n] f (x) = 1n [xn − 1](xg(x))ng(f(x))=x, and [x^n]f(x)=\frac 1 n[x^{n-1}](\frac{x}{g(x)})^ng(f(x))=x, and [xn] f (x) = n 1 [xn − 1](g(x)x) n
Extended Lagrangian inversion
There are [x n] H (f (x)) = 1n [xn − 1]H ′ (x) (x g (x)) n [x ^ n] H (f (x)) = \ frac 1n [x ^ {n-1}] H '(x) (\ frac {x} {g (x)}) ^ n [xn] H (f (x)) = N1 [xn − 1]H ′ (x)(g(x)x) n

First, the number of undirected simple connected graphs with roots is considered
You can use ln ⁡ \ lnln to find the number of multiply points without roots
Let EGFEGFEGF be H(x)H(x)H(x)
Let Bib be the double number of labeled points of i+1i+1i+1
Consider for an undirected connected graph with roots
The root may be in multiple point pairs
Multiple connected blocks will be formed after deleting the root
Consider deleting both sides of root and all points
Then each connected block will become several connected graphs
The generating function of a connected block
The number of enumeration connected graphs is ∑ K BK K! H(x)k \ sum {K} \ frac {B} {K!} H (x) ^ k ∑ k!bk H(x)k
Let B(x) = ∑ i Bi i! Xib (x) = \ sum ﹣ i \ frac {B} {i!} x ^ IB (x) = ∑ i!bi xi
There are
H(x)=xe(B(H(x)))H(x)=xe^{(B(H(x)))}H(x)=xe(B(H(x)))
Then H(x)eB(H(x))=x\frac{H(x)}{e^{B(H(x))}}=xeB(H(x))H(x) = x
Let h − 1(x)H^{-1}(x)H − 1(x) be the compound inverse of HHH
Then there are
H−1(x)=xeB(x)H^{-1}(x)=\frac{x}{e^{B(x)}}H−1(x)=eB(x)x​
B(x)=ln⁡(xH−1(x))B(x)=\ln(\frac{x}{H^{-1}(x)})B(x)=ln(H−1(x)x​)
Let G(x)=ln (H(x)x)G(x)=\ln(\frac{H(x)}{x})G(x)=ln(xH(x))
Then G(H − 1(x))=B(x)G(H^{-1}(x))=B(x)G(H − 1(x))=B(x)
From the extended Lagrangian inversion
[xn]B(x)=[xn]G(H−1(x))=1n[xn−1]G′(x)(xH(x))=1n[xn−1]G′(x)(H(x)x)−n[x^n]B(x)=[x^n]G(H^{-1}(x))=\frac{1}{n}[x^{n-1}]G'(x)(\frac{x}{H(x)})=\frac{1}{n}[x^{n-1}]G'(x)(\frac{H(x)}{x})^{-n}[xn]B(x)=[xn]G(H−1(x))=n1​[xn−1]G′(x)(H(x)x​)=n1​[xn−1]G′(x)(xH(x)​)−n
The fast power of polynomials can be realized by ln + exp \ ln+\expln+exp
Because Σ s\sum s Σ s is guaranteed
This part of complexity is O(nlogn)O(nlogn)O(nlogn)

Let B(x) = ∑ i ∈ Sbii!xi, F(x) be the EGFB(x) = \ sum {i \ in S} \ frac {B} {i!} x ^ i, F(x) be the EGFB(x) = ∑ i ∈ S i!bi xi, F(x) be the EGF of the rooted graph
It can also be obtained from the above derivation
F(x)=xeB(F(x))F(x)=xe^{B(F(x))}F(x)=xeB(F(x))
F(x)eB(F(x))=x\frac{F(x)}{e^{B(F(x))}}=xeB(F(x))F(x)​=x
F−1(x)=xeB(x)F^{-1}(x)=\frac{x}{e^{B(x)}}F−1(x)=eB(x)x​
[xn]F(x)=1n[xn−1](xF−1(x))n=1n[xn−1]eB(x)n[x^n]F(x)=\frac 1 n[x^{n-1}](\frac{x}{F^{-1}(x)})^n=\frac 1 n[x^{n-1}]e^{B(x)n}[xn]F(x)=n1​[xn−1](F−1(x)x​)n=n1​[xn−1]eB(x)n
Do exp again
Notice that the FFF is rooted
And then divide by nnn

Complexity O(nlogn)O(nlogn)O(nlogn)

#include<bits/stdc++.h>
using namespace std;
#define cs const
#define re register
#define pb push_back
#define pii pair<int,int>
#define ll long long
#define fi first
#define se second
#define bg begin
cs int RLEN=1<<20|1;
inline char gc(){
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob)&&(ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob)?EOF:*ib++;
}
inline int read(){
    char ch=gc();
    int res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline ll readll(){
    char ch=gc();
    ll res=0;bool f=1;
    while(!isdigit(ch))f^=ch=='-',ch=gc();
    while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=gc();
    return f?res:-res;
}
inline int readstring(char *s){
	int top=0;char ch=gc();
	while(isspace(ch))ch=gc();
	while(!isspace(ch)&&ch!=EOF)s[++top]=ch,ch=gc();
	return top;
}
template<class tp>inline void chemx(tp &a,tp b){a<b?a=b:0;}
template<class tp>inline void chemn(tp &a,tp b){a>b?a=b:0;}
cs int mod=998244353;
inline int add(int a,int b){return (a+=b)>=mod?(a-mod):a;}
inline int dec(int a,int b){a-=b;return a+(a>>31&mod);}
inline int mul(int a,int b){static ll r;r=1ll*a*b;return (r>=mod)?(r%mod):r;}
inline void Add(int &a,int b){(a+=b)>=mod?(a-=mod):0;}
inline void Dec(int &a,int b){a-=b,a+=a>>31&mod;}
inline void Mul(int &a,int b){static ll r;r=1ll*a*b;a=(r>=mod)?(r%mod):r;}
inline int ksm(int a,int b,int res=1){if(a==0&&b==0)return 0;for(;b;b>>=1,Mul(a,a))(b&1)&&(Mul(res,a),1);return res;}
inline int Inv(int x){return ksm(x,mod-2);}
inline int fix(int x){return (x<0)?x+mod:x;}
typedef vector<int>poly;
namespace Poly{
	cs int C=18,M=(1<<C)|5,G=3;
	int *w[C+1],rev[M],iv[M];
	inline void init_w(){
		for(int i=1;i<=C;i++)w[i]=new int[((1<<(i-1))|1)];
		int wn=ksm(G,(mod-1)/(1<<C));w[C][0]=1;
		for(int i=1,l=(1<<(C-1));i<l;i++)w[C][i]=mul(w[C][i-1],wn);
		for(int i=C-1;i;i--)
		for(int j=0,l=1<<(i-1);j<l;j++)w[i][j]=w[i+1][j<<1];
		iv[0]=iv[1]=1;
		for(int i=2;i<M;i++)iv[i]=mul(mod-mod/i,iv[mod%i]);
	}
	inline void init_rev(int lim){
		for(int i=0;i<lim;i++)rev[i]=(rev[i>>1]>>1)|((i&1)*(lim>>1));
	}
	inline void ntt(int *f,int lim,int kd){
		for(int i=0;i<lim;i++)if(i>rev[i])swap(f[i],f[rev[i]]);
		for(int mid=1,l=1,a0,a1;mid<lim;mid<<=1,l++)
		for(int i=0;i<lim;i+=mid<<1)
		for(int j=0;j<mid;j++)
		a0=f[i+j],a1=mul(w[l][j],f[i+j+mid]),f[i+j]=add(a0,a1),f[i+j+mid]=dec(a0,a1);
		if(kd==-1){
			reverse(f+1,f+lim);
			for(int i=0;i<lim;i++)Mul(f[i],iv[lim]);
		}
	}
	inline poly operator *(poly a,poly b){
		int deg=a.size()+b.size()-1;
		if(deg<=32){
			poly c(deg,0);
			for(int i=0;i<a.size();i++)
			for(int j=0;j<b.size();j++)
			Add(c[i+j],mul(a[i],b[j]));
			return c;
		}
		int lim=1;
		while(lim<deg)lim<<=1;
		init_rev(lim);
		a.resize(lim),ntt(&a[0],lim,1);
		b.resize(lim),ntt(&b[0],lim,1);
		for(int i=0;i<lim;i++)Mul(a[i],b[i]);
		ntt(&a[0],lim,-1),a.resize(deg);
		return a;
	}
	inline poly Inv(poly a,int deg){
		poly b(1,::Inv(a[0])),c;
		for(int lim=4;lim<(deg<<2);lim<<=1){
			c.resize(lim>>1);
			for(int i=0;i<(lim>>1);i++)c[i]=(i<a.size()?a[i]:0);
			c.resize(lim),b.resize(lim);
			init_rev(lim);
			ntt(&b[0],lim,1),ntt(&c[0],lim,1);
			for(int i=0;i<lim;i++)Mul(b[i],dec(2,mul(b[i],c[i])));
			ntt(&b[0],lim,-1),b.resize(lim>>1);
		}b.resize(deg);return b;
	}
	inline poly deriv(poly a){
		for(int i=0;i<(int)a.size()-1;i++)a[i]=mul(a[i+1],i+1);
		a.pop_back();return a;
	}
	inline poly integ(poly a){
		a.pb(0);
		for(int i=a.size()-1;i;i--)a[i]=mul(a[i-1],iv[i]);
		a[0]=0;return a;
	}
	inline poly Ln(poly a,int deg){
		a=integ(deriv(a)*Inv(a,deg)),a.resize(deg);
		return a;
	}
	inline poly Exp(poly a,int deg){
		poly b(1,1),c;
		for(int lim=2;lim<(deg<<1);lim<<=1){
			c=Ln(b,lim);
			for(int i=0;i<lim;i++)c[i]=dec(i<a.size()?a[i]:0,c[i]);
			Add(c[0],1),b=b*c,b.resize(lim);
		}b.resize(deg);return b;
	}
}
using namespace Poly;
cs int N=100005;
int fac[N],ifac[N];
inline void init_inv(){
	fac[0]=ifac[0]=1;
	for(int i=1;i<N;i++)fac[i]=mul(fac[i-1],i);
	ifac[N-1]=Inv(fac[N-1]);
	for(int i=N-2;i;i--)ifac[i]=mul(ifac[i+1],i+1);
}
int n,m;
int main(){
	#ifdef Stargazer
	freopen("lx.in","r",stdin);
	#endif
	init_w(),init_inv();
	n=read(),m=read();
	poly H(n+2);
	for(int i=0;i<=n+1;i++)H[i]=mul(ifac[i],ksm(2,1ll*i*(i-1)/2%(mod-1)));
	H=Ln(H,n+2);
	for(int i=0;i<=n+1;i++)Mul(H[i],i);
	poly G(n+1);
	for(int i=0;i<=n;i++)G[i]=H[i+1];
	poly B(n+1),P=G;G=deriv(Ln(G,n+1));
	P=Ln(P,n+1);
	for(int i=1;i<=m;i++){
		int s=read()-1;
		poly a(s),b(s);
		for(int j=0;j<s;j++)a[j]=G[j],b[j]=P[j];
		for(int j=0;j<b.size();j++)Mul(b[j],mod-s);
		b=Exp(b,s)*a;
		B[s]=mul(iv[s],b[s-1]);
	}
	for(int i=0;i<B.size();i++)Mul(B[i],n);
	B=Exp(B,n+1);
	cout<<mul(B[n-1],mul(fac[n-1],iv[n]))<<'\n';
	return 0;
}
Published 600 original articles, praised 195, visited 50000+
His message board follow

Posted on Thu, 12 Mar 2020 09:44:38 -0400 by Angry Coder