LOJ6402 yww 与校门外的树

yww 与校门外的树

二中的校门外有一排树,一共 \(n\) 棵。每棵树的高度为 \([0,1]\) 之间的随机小数。每棵树上都有一个苹果。

zjt 把这 \(n\) 棵树从左到右编号为 \(1\sim n\)。zjt 还会在某些树之间挂上绳索。设第 \(i\) 棵树的高度为 \(a_i\) 。如果对于两棵树 \(i,j\) 满足 \(i\(a_i ,那么 zjt 就会在第 \(i\) 棵树与第 \(j\) 棵树之间挂上一条绳索。这些绳索是双向的。

这时,有很多猴子路过了这里,你可以认为是 \(n\) 只,或是 \(2n\) 只,或是 \(\infty\) 只。这些猴子会依次选择一棵有苹果的树(如果所有树上都没有苹果就不选),然后把这棵树以及可以通过绳索去到的其他树上的苹果全部摘下来。如果一只猴子摘下来了 \(x\) 个苹果,那么猴群的团结度就会乘以 \(x\) 。猴群的初始团结度为 \(1\) 。如果一只猴子没有摘到苹果,那么他就会离开猴群,所以不会影响团结度。

猴王想知道猴群的期望团结度是多少。请你帮帮他。

设答案为 \(s\) ,显然 \(s\times n!\) 是一个整数。所以你只需要告诉他 \(\mathit{ans}=(s\times n!)\bmod 998244353\) 的值 。

对于 \(100\%\) 的数据:\(1\leq n\leq 5\times 10^5\)

题解

https://jklover.hs-blog.cf/2020/06/17/Loj-6402-yww-与校门外的树/

多项式求逆.

首先这个随机过程可以等价于随机出了一个 \(1\sim n\) 的排列,需要对每个排列的答案求和.

不难发现,各个连通块是一段连续的区间,且两个相邻的连通块之间一定是左侧的最小值大于右侧的最大值.

\(F(x)\) 表示长度为 \(i\) 的排列形成一个连通块的 OGF, 若干个这样的结构会组合成一个排列,且合并时顺序固定.

那么设 \(P(x)=\sum i!x^i​\) ,则有 \(\frac{1}{1-F(x)}=P​\) ,得出 \(F(x)=1-\frac{1}{P(x)}​\) .

考虑如何计算答案,只需要把贡献放入 \(F​(x)\) 的每一项中,再用若干个结构卷起来组合成排列即可.

\(G(x)=\sum f_1\cdot i\cdot x^i\) ,则 \([x^n]\frac{1}{1-G(x)}\) 即为所求.

需要实现多项式乘法及求逆,时间复杂度 \(O(n\log n)\) .

CO int N=1<<20;
int omg[2][N],rev[N];
int fac[N],inv[N],ifac[N];

void NTT(poly&a,int dir){
	int lim=a.size(),len=log2(lim);
	for(int i=0;i>1]>>1|(i&1)<<(len-1);
	for(int i=0;i();
	poly f=~poly(fac,fac+n+1);
	f[0]=add(1,mod-f[0]);
	for(int i=1;i<=n;++i) f[i]=mod-f[i];
	f[0]=add(1,mod-mul(0,f[0]));
	for(int i=1;i<=n;++i) f[i]=mod-mul(i,f[i]);
	f=~f;
	printf("%d\n",f[n]);
	return 0;
}

你可能感兴趣的:(LOJ6402 yww 与校门外的树)