「2020-2021 集训队作业」Yet Another Permutation Problem
「2020-2021 集训队作业」Yet Another Permutation Problem
题目大意
对于一个初始为 \(1,2,\ldots n\) 的排列,每次操作为选择一个数放到开头或者结尾,求 \(k\) 次操作能够生成的排列数
对于 \(k=0,1,\ldots ,n-1\) 求解
\[ \ \]
模型转化
容易发现,对于一个排列,生成它的最小次数取决于中间保留段的长度
而保留段实际上是任何一个上升子段
设一个排列的最长上升子段为 \(l\) ,那么最少操作步骤就是 \(n-l\)
那么对于 \(k\) ,合法的序列就是存在一个长度 \(\ge n-k\) 的上升子段
存在不好算,改为计算任何一个上升子段 \(<n-k\) 的数量
为了便于描述,令下文的 \(k=n-k-1\)
\[ \ \]
生成函数构造
考虑一个序列是由若干上升段构成的,设一个长度为 \(l\) 的上升段的权值为 \([l\leq k]\)
那么排列的权值就是上升段权值之积
容易想到用 \(\text{EGF}\) 合并上升段,但是直接的统计,我们无法保证上升段之间无法拼接
假设我们确定了一个单位上升段的 \(\text{EGF}\) 为 \(G(x)\) , \(\text{OGF}\) 为 \(F(x)\)
那么按照上面 \(\text{Naive}\) 的计算,上升段之间的合并为有序拼接,即 \(\displaystyle \sum_{i=0}G^i(x)=\frac{1}{1-G(x)}\)
容易发现,这样的计算,会导致一个长度为 \(l\) 的极长上升段被分解成若干小段
也就是被计算了 \(\displaystyle [x^l](\sum_{i=0}F^i(x))=[x^l]\frac{1}{1-F(x)}\) 次
在合法的计算中,我们希望, \([x^l]\frac{1}{1-F(x)}\) 恰好为权值 \([l\leq k]\)
也就是说,我们希望 \(\displaystyle \frac{1}{1-F(x)}=H(x)=\sum_{i=0}^kx^i=\frac{x^{k+1}-1}{x-1}\)
那么可以反向由 \(H(x)\) 构造出我们想要的 \(F(x)\) ,从而得到 \(G(x)\) ,再进行求解
\[ \ \]
答案计算
\(\displaystyle F(x)=1-\frac{1}{H(x)}=1-\frac{x-1}{x^{k+1}-1}=\frac{x-x^{k+1}}{1-x^{k+1}}\)
可以爆算得到 \(F(x)\) ,从而得到 \(G(x)\) ,然后暴力求逆就是 \(O(n^2)\)
优化:
\(1-x^{k+1}\) 的逆,只包含 \(\frac{n}{k+1}\) 项,所以 \(G(x)\) 只含 \(2\frac{n}{k+1}\) 项
即 \(\displaystyle F(x)=\sum_{d=0}x^{d(k+1)+1}-\sum_{d=1}x^{d(k+1)}\) , \(G(x)\) 就是除一个阶乘
这样暴力求逆就是 \(O(n^2\ln n)\)
(不是你干嘛要真的求逆,直接进行 \(G(x)\) 的叠加就可以了)
1 | const int N=1010; |