Codeforces Round 641 F2. Slime and Sequences (生成函数)(拉格朗日反演)

传送门

  • 注意到好的序列到一个排列是一个双射,在序列上的数 a p i a_{p_i} api 等于 i i i 前方的小于号个数加一,其中小于号指的是相邻两个数的大小关系,下面我们对这个排列进行计数

  • f i , j f_{i,j} fi,j 表示长度为 i i i 至少 j j j < < < 的个数,恰为斯特林数 S i , i − j S_{i,i-j} Si,ij,每一组内钦定递增
    g i , j g_{i,j} gi,j 表示正好 j j j < < < 的个数(可以 O ( n 2 ) O(n^2) O(n2) 简单 d p dp dp

g i , j = ∑ k ≥ j ( − 1 ) k − j ( k j ) f i , j g_{i,j}=\sum_{k\ge j}(-1)^{k-j}\binom{k}{j}f_{i,j} gi,j=kj(1)kj(jk)fi,j

  • 考虑每个数的贡献,钦定它前面有 i i i < < <
    a n s i = ∑ j = i n g j , i ∗ ( n j ) ( n − j ) ! = ∑ j = i n ∑ k = i n S j , j − k ( − 1 ) k − i ( k i ) n ! j ! = n ! ∑ k = i n ( − 1 ) k − i ( k i ) ∑ j = k n [ x j ] ( e x − 1 ) j − k ans_i=\sum_{j=i}^ng_{j,i}*\binom{n}{j}(n-j)!\\=\sum_{j=i}^n\sum_{k=i}^nS_{j,j-k}(-1)^{k-i}\binom{k}{i}\frac{n!}{j!}\\=n!\sum_{k=i}^n(-1)^{k-i}\binom{k}{i}\sum_{j=k}^n[x^j](e^x-1)^{j-k} ansi=j=ingj,i(jn)(nj)!=j=ink=inSj,jk(1)ki(ik)j!n!=n!k=in(1)ki(ik)j=kn[xj](ex1)jk

  • 考虑快速求出 f k = ∑ j = k n [ x j ] ( e x − 1 ) j − k = [ x k ] ∑ j = 1 n − k ( e x − 1 x ) j = [ x k ] F n − k + 1 − F F − 1 f_k=\sum_{j=k}^n[x^j](e^x-1)^{j-k}\\=[x^k]\sum_{j=1}^{n-k}(\frac{e^x-1}{x})^{j}\\=[x^k]\frac{F^{n-k+1}-F}{F-1} fk=j=kn[xj](ex1)jk=[xk]j=1nk(xex1)j=[xk]F1Fnk+1F

  • 考虑对每个 k k k 求出( F = e x − 1 x F=\frac{e^x-1}{x} F=xex1 G = e x − 1 G=e^x-1 G=ex1
    [ x k ] F n − k + 1 1 − F = [ x n + 1 ] G n − k + 1 1 − F = [ x n + 1 y n − k + 1 ] ∑ i ≥ 0 ( y G ) i 1 − F = [ x n + 1 y n − k + 1 ] 1 1 − y G 1 1 − F [x^k]\frac{F^{n-k+1}}{1-F}=[x^{n+1}]\frac{G^{n-k+1}}{1-F}\\=[x^{n+1}y^{n-k+1}]\sum_{i\ge 0}\frac{(yG)^i}{1-F}\\=[x^{n+1}y^{n-k+1}]\frac{1}{1-yG}\frac{1}{1-F} [xk]1FFnk+1=[xn+1]1FGnk+1=[xn+1ynk+1]i01F(yG)i=[xn+1ynk+1]1yG11F1
    构造 ϕ ( x ) \phi(x) ϕ(x) 使得 F = ϕ ( G ) F=\phi(G) F=ϕ(G),则 G = x F , G ϕ ( G ) = x G=xF,\frac{G}{\phi(G)}=x G=xF,ϕ(G)G=x
    聪明的你们肯定看出构造的用意了,令 T ( x ) = x ϕ ( x ) T(x)=\frac{x}{\phi(x)} T(x)=ϕ(x)x,拉个朗日反演
    H ( x ) = H ( T ( G ) ) = 1 1 − y x 1 1 − ϕ ( x ) H(x)=H(T(G))=\frac{1}{1-yx}\frac{1}{1-\phi(x)} H(x)=H(T(G))=1yx11ϕ(x)1
    [ x n + 1 ] [ y n − k + 1 ] H ( G ) = [ x n ] [ y n − k + 1 ] 1 n + 1 d H d x ( x T ) n + 1 = 1 n + 1 [ y n − k + 1 ] [ x n ] ( − ( ( 1 − x y ) ( 1 − ϕ ( x ) ) ) ′ ( 1 − x y ) 2 ( 1 − ϕ ( x ) ) 2 ϕ ( x ) n + 1 ) = 1 n + 1 [ y n − k + 1 ] [ x n ] ( y ( 1 − ϕ ( x ) ) + ϕ ( x ) ′ ( 1 − x y ) ( 1 − x y ) 2 ( 1 − ϕ ( x ) ) 2 ) ϕ ( x ) n + 1 = 1 n + 1 [ y n − k + 1 ] [ x n ] ( y ( 1 − x y ) 2 ( 1 − ϕ ( x ) ) + ϕ ( x ) ′ ( 1 − x y ) ( 1 − ϕ ( x ) ) 2 ϕ ( x ) n + 1 ) [x^{n+1}][y^{n-k+1}]H(G)=[x^n][y^{n-k+1}]\frac{1}{n+1}\frac{\text{d}H}{\text{d}x}(\frac{x}{T})^{n+1}\\=\frac{1}{n+1}[y^{n-k+1}][x^n](\frac{-((1-xy)(1-\phi(x)))'}{(1-xy)^2(1-\phi(x))^2}\phi(x)^{n+1})\\=\frac{1}{n+1}[y^{n-k+1}][x^n](\frac{y(1-\phi(x))+\phi(x)'(1-xy)}{(1-xy)^2(1-\phi(x))^2})\phi(x)^{n+1}\\ =\frac{1}{n+1}[y^{n-k+1}][x^n](\frac{y}{(1-xy)^2(1-\phi(x)) }+\frac{\phi(x)'}{(1-xy)(1-\phi(x))^2}\phi(x)^{n+1}) [xn+1][ynk+1]H(G)=[xn][ynk+1]n+11dxdH(Tx)n+1=n+11[ynk+1][xn]((1xy)2(1ϕ(x))2((1xy)(1ϕ(x)))ϕ(x)n+1)=n+11[ynk+1][xn]((1xy)2(1ϕ(x))2y(1ϕ(x))+ϕ(x)(1xy))ϕ(x)n+1=n+11[ynk+1][xn]((1xy)2(1ϕ(x))y+(1xy)(1ϕ(x))2ϕ(x)ϕ(x)n+1)

= 1 n + 1 [ y n − k + 1 ] [ x n ] ϕ ( x ) n + 1 ( 1 ( 1 − ϕ ( x ) ) ∑ t ≥ 0 x t y t + 1 ( t + 1 ) + ϕ ( x ) ′ ( 1 − ϕ ( x ) ) 2 ∑ t ≥ 0 x t y t ) = 1 n + 1 [ x n ] ϕ ( x ) n + 1 { 1 ( 1 − ϕ ( x ) ) ( n − k + 1 ) x n − k + ϕ ( x ) ′ ( 1 − ϕ ( x ) ) 2 x n − k + 1 } = 1 n + 1 ( [ x k ] ( n − k + 1 ) ϕ ( x ) n + 1 1 − ϕ ( x ) + [ x k − 1 ] ϕ ( x ) ′ ϕ ( x ) n + 1 ( 1 − ϕ ( x ) ) 2 ) =\frac{1}{n+1}[y^{n-k+1}][x^n]\phi(x)^{n+1}(\frac{1}{(1-\phi(x))}\sum_{t\ge 0}x^ty^{t+1}(t+1)+\frac{\phi(x)'}{(1-\phi(x))^2}\sum_{t\ge 0}x^ty^t)\\=\frac{1}{n+1}[x^n]\phi(x)^{n+1}\{\frac{1}{(1-\phi(x))}(n-k+1)x^{n-k}+\frac{\phi(x)'}{(1-\phi(x))^2}x^{n-k+1}\}\\=\frac{1}{n+1}([x^k]\frac{(n-k+1)\phi(x)^{n+1}}{1-\phi(x)}+[x^{k-1}]\frac{\phi(x)'\phi(x)^{n+1}}{(1-\phi(x))^2}) =n+11[ynk+1][xn]ϕ(x)n+1((1ϕ(x))1t0xtyt+1(t+1)+(1ϕ(x))2ϕ(x)t0xtyt)=n+11[xn]ϕ(x)n+1{(1ϕ(x))1(nk+1)xnk+(1ϕ(x))2ϕ(x)xnk+1}=n+11([xk]1ϕ(x)(nk+1)ϕ(x)n+1+[xk1](1ϕ(x))2ϕ(x)ϕ(x)n+1)

  • ϕ ( x ) = x ln ⁡ ( x + 1 ) \phi(x)=\frac{x}{\ln(x+1)} ϕ(x)=ln(x+1)x O ( n log ⁡ n ) O(n\log n) O(nlogn)
#include<bits/stdc++.h>
#define pb push_back
#define cs const
#define poly vector<int>
using namespace std;
cs int Mod = 998244353;
int add(int a, int b){ return a + b >= Mod ? a + b - Mod : a + b; }
int dec(int a, int b){ return a - b < 0 ? a - b + Mod : a - b; }
int mul(int a, int b){ return 1ll * a * b % Mod; }
int ksm(int a, int b){ int as=1; for(;b;b>>=1,a=mul(a,a)) if(b&1) as=mul(as,a); return as; }
void Add(int &a, int b){ a = add(a, b); }
void Dec(int &a, int b){ a = dec(a, b); }
void Mul(int &a, int b){ a = mul(a, b); }
cs int K = 18, N = 1 << K | 5;
int n, fc[N], ifc[N], iv[N];
int *w[K+1], rv[N], bit, up;
void output(poly a){ for(int i=0; i<a.size(); i++) cout<<a[i]<<" "; puts(""); }
void fc_init(int n){
	fc[0]=fc[1]=ifc[0]=ifc[1]=1;
	for(int i=2; i<=n; i++) fc[i]=mul(fc[i-1],i);
	for(int i=2; i<=n; i++) ifc[i]=mul(ifc[i-1],iv[i]);
}
void NTT_init(){
	for(int i=1; i<=K; i++) w[i]=new int[1<<(i-1)];
	int wn=ksm(3,(Mod-1)/(1<<K)); w[K][0]=1;
	for(int i=1; i<(1<<(K-1)); i++) w[K][i]=mul(w[K][i-1],wn);
	for(int i=K-1;i;i--) for(int j=0;j<(1<<(i-1));j++) w[i][j]=w[i+1][j<<1]; 
	iv[0]=iv[1]=1; for(int i=2; i<=(1<<K); i++) iv[i]=mul(Mod-Mod/i,iv[Mod%i]);
} 
void init(int deg){
	up=1; bit=0; while(up<deg) up<<=1,++bit; 
	for(int i=0; i<up; i++) rv[i]=(rv[i>>1]>>1)|((i&1)<<(bit-1));
}
poly operator - (poly a, poly b){
	if(a.size()<b.size()) a.resize(b.size());
	for(int i=0; i<(int)b.size(); i++) Dec(a[i],b[i]); return a;
}
poly divx(poly a){
	for(int i=0; i<(int)a.size(); i++) a[i]=a[i+1];
	return a.pop_back(), a;
}
void NTT(poly &a, int typ=1){
	for(int i=0; i<up; i++) if(i<rv[i]) swap(a[i],a[rv[i]]);
	for(int i=1,l=1;i<up;i<<=1,++l)
	for(int j=0; j<up; j+=(i<<1))
	for(int k=0; k<i; k++){
		int x=a[k+j], y=mul(w[l][k],a[k+j+i]);
		a[k+j]=add(x,y); a[k+j+i]=dec(x,y);
	} if(typ==-1){
		reverse(a.begin()+1,a.end());
		for(int i=0,iv=ksm(up,Mod-2); i<up; i++) Mul(a[i],iv);
	}
}
poly operator * (poly a, poly b){
	int dg=a.size()+b.size()-1; 
	if(a.size()<=32||b.size()<=32){
		poly c(dg,0);
		for(int i=0; i<(int)a.size(); i++)
		for(int j=0; j<(int)b.size(); j++)
		Add(c[i+j],mul(a[i],b[j])); return c;
	} init(dg); a.resize(up); b.resize(up); NTT(a); NTT(b);
	for(int i=0; i<up; i++) Mul(a[i],b[i]); 
	NTT(a,-1); a.resize(dg); return a;
}
poly inv(poly a, int deg){
	poly b(1,ksm(a[0],Mod-2)),c;
	for(int lim=2; (lim>>1)<deg; lim<<=1){
		c.resize(lim); init(lim<<1);
		for(int i=0; i<lim; i++) c[i]=i<(int)a.size()?a[i]:0;
		c.resize(up); b.resize(up); NTT(c); NTT(b);
		for(int i=0; i<up; i++) Mul(b[i],dec(2,mul(b[i],c[i])));
		NTT(b,-1); b.resize(lim); 
	} b.resize(deg); return b;
}
poly deriv(poly a){
	for(int i=0; i+1<(int)a.size(); i++) a[i]=mul(i+1,a[i+1]);
	a.pop_back(); return a;
}
poly integ(poly a){
	a.pb(0);
	for(int i=a.size()-1;i;i--) a[i]=mul(iv[i],a[i-1]);
	a[0]=0; return a;
}
poly ln(poly a, int dg){
	if(dg==-1) dg=a.size();
	a=integ(deriv(a)*inv(a,dg)); a.resize(dg); return a;
}
poly Exp(poly a, int dg){
	if(dg==-1) dg = a.size(); poly b(1,1), c;
	for(int lim=2; lim<(dg<<1); lim<<=1){
		c=ln(b,lim); Dec(c[0],1);
		for(int i=0; i<lim; i++) c[i]=dec(i<(int)a.size()?a[i]:0,c[i]);
		b=b*c; b.resize(lim);
	} b.resize(dg); return b;
}
poly polypw(poly a, int k, int dg){ 
	a = ln(a,dg); 
	for(int i=0; i<(int)a.size(); i++) Mul(a[i],k);
	return Exp(a,dg);
}
int main(){
	#ifdef FSYolanda
	freopen("1.in","r",stdin);
	#endif
	scanf("%d",&n); NTT_init(); fc_init(n+5);
	poly phi(2,1); phi = ln(phi,n+3); phi = inv(divx(phi),n+3);
	poly t = poly(1,1) - phi; 
	t = inv(divx(t),n+3); poly tt = t * t; tt.resize(n+3);
	poly mt = polypw(phi,n+1,n+3), dt = deriv(phi);
	t = mt * t; tt = mt * tt; t.resize(n+3); tt.resize(n+3);
	tt = tt * dt; tt.resize(n+3);
	poly em(n+3,0);
	for(int i=0; i<=n+2; i++) em[i]=ifc[i+1];
	em=em*inv(divx(poly(1,1)-em),n+3);
	poly f(n+1,0);
	for(int i=0,iv=ksm(n+1,Mod-2); i<n; i++){
		f[i] = mul(iv,add(mul(t[i+1],n-i+1), tt[i+1]));
		f[i] = dec(em[i+1],f[i]); Mul(f[i],fc[i]);
	} poly g(n,0);
	for(int i=0; i<n; i++) g[i]=(i&1)?dec(0,ifc[i]):ifc[i];
	reverse(g.begin(),g.end()); g = g * f;
	for(int i=0; i<n; i++) cout<<mul(ifc[i],mul(fc[n],g[i+n-1]))<<" ";
	return 0;	
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

FSYo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值