继续数数。
考虑计算 i 步以后还没有连续 k 张卡的概率。
容易发现可以转化为对于所有没有连续 k 张卡的状态,计算 i 步后到达该状态的概率并求和。
设 fi 表示从 m 张卡里选择 i 张卡使得没有连续 k 张卡的方案数。
则答案即 ∞∑i=0m−1∑j=0fjj∑u=0(ju)(−1)j−u(um)i=m−1∑j=0fjj∑u=0(ju)(−1)j−u∞∑i=0(um)i=m−1∑j=0fjj∑u=0(ju)(−1)j−umm−u
后面的和式可以随便卷积一下计算,那么问题转化为计算 fi。
容易发现实际上可以将序列 a 排序后划分为若干极大连续段,对于每个极大连续段分别计算答案再分治 NTT 卷起来。
那么对于一个长度为 n 的连续段,考虑计算其中的 fi。
略加思考后不难发现这个东西就是 [xn+1](k∑j=1xj)n−i+1
即,将 n 张卡的状态视作 0/1;对于每个 0,将其与之前最长的连续 1(可以为空)合并在一起考虑;那么每一个这样的块的长度便是 1…k。
此外,需要在最后强制加入一个 0。
那么设 G(x)=x−xk+11−x,不难发现,若写出 f 的生成函数,则有 n∑i=0fizi=[xn+1]11−G(x)z
考虑对这样一个二元生成函数应用扩展拉格朗日反演,有 [xn+1]11−G(x)z=1n+1[xn]z(1−xz)2(xG−1(x))n+1
其中 G−1 为 G 的复合逆。
若求出 G−1,结合多项式求逆和多项式快速幂并展开 z(1−xz)2 便可以求得 fi。
于是问题变为求解 G−1(x)。
设 F=G−1,考虑牛顿迭代之。
设已得 G(F0(x))≡x(modxn)
在 F(x)=F0(x) 处泰勒展开 G(F(x))≡G(F0(x))+G′(F0(x))(F(x)−F0(x))(modx2n)F(x)≡F0(x)+x−G(F0(x))G′(F0(x))(modx2n)
而易得 G′(x)=kxk+1−(k+1)xk+1(1−x)2
故倍增 + 多项式全家桶即可(雾
此部分仅有一个 log,算上分治 NTT 总复杂度 O(mlog2m)。
(当然这一个 log 顶人家不知道多少次分治 NTT)
貌似有更优美做法,懒得学了(
生成函数暴力美学(
代码:
1 |
|