一个计数问题(cf1295F)

Educational Codeforces Round 81 Problem F. Good Contest

题意

一个长度为\(n\)的整数数列,第\(i\)个元素在\([l_i, r_i]\)里均匀随机,求它单调不增的概率。由于答案是个有理数,输出它在模\(998244353\)下的值。

题面里定义的inversion很奇怪,所以我一开始把它看成单调不减了,测样例才发现。不过也没关系,把序列翻转一下就行,后面就按单调不减写了。

\(l_i, r_i\)的范围很大:\(0 \leq l_i \leq r_i \leq 998244351\),仅仅让作为分母的\(r_i-l_i+1\)不达到\(998244353\)以保证逆元存在。\(n \leq 50\)

观察

首先考虑朴素的dp:\(dp[i][j]\)表示第\(i\)个元素是\(j\),并且以它为结尾的前缀单调不减的方案数,转移是平凡的:\(dp[i][j]=\sum_{l_{i-1} \leq k \leq j} dp[i-1][k]\)

注意到\(n\)不是很大,那么离散化之后值域就被分成了\(O(n)\)段。按这个思路做下去的话,就是要考虑每一段中的dp值有什么性质,一起处理。为了找到这个性质,首先观察一个简单的情况:所有区间均相同,\(l=0\)\(r\)充分大。这时考虑差分,\(dp[i][j]\)就是将\(j\)拆分为\(i\)个非负整数之和的方案数了,即\(dp[i][j]=\begin{pmatrix} j+i-1 \\ i-1 \end{pmatrix}\)

再考虑上面的dp转移,这提示我们用到组合数的这个性质:\(\sum_{k=0}^r \begin{pmatrix} t+k \\ t \end{pmatrix} = \begin{pmatrix} t+r+1 \\ t+1 \end{pmatrix}\),这意味着如果值域中某一段的dp值为\(\begin{pmatrix} t \\ t \end{pmatrix}, \begin{pmatrix} t+1 \\ t \end{pmatrix}, \dots\),那么它对下一阶段同一段的贡献依然保持这一形式,不过\(t\)会增加\(1\)

除了上一阶段同一段的贡献,上一阶段更小的段也会产生贡献:使当前段所有dp值加上一个常数,这可以被看成\(t=0\)的情况乘上一个常数。因此,一段的dp值可以被拆分为若干个\(c\begin{pmatrix} t \\ t \end{pmatrix}, c\begin{pmatrix} t+1 \\ t \end{pmatrix}, \dots\)的和的形式,并且在转移中依然保持这个形式。其实也就是归纳证明了这个表示方法。

这样一来其实已经做出来了,对每个阶段每个值域段存储一个\(c-t\) pair的列表即可。在转移时,直接把上一阶段同一值域段的列表复制过来,所有\(t\)\(1\),再增加一项更小的值域段的贡献。这样,列表的长度每过一个阶段至多增加\(1\),是\(O(n)\)的。转移时从小到大枚举值域段,累加前一阶段贡献的同时算出这一阶段。这里要做的是把前一阶段当前值域段的dp值之和累加进去。一个\(c-t\) pair对应的和是一个组合数,经过\(O(n^2)\)的预处理是可以\(O(1)\)做的。因此对于\(O(n)\)段,每段枚举\(O(n)\)\(c-t\) pair,每阶段耗时\(O(n^2)\)。同值域段转移时复制vector也是一样的复杂度,所以复杂度是\(O(n^3)\)

因为\(n\)很小,我比赛的时候并没有预处理组合数,复杂度实际是\(O(n^4)\)的,依然跑得飞快。

posted @ 2020-02-01 12:17  lkmcfj  阅读(253)  评论(0编辑  收藏  举报