CF1580B Mathematics Curriculum 题解

求满足以下条件的排列个数:

  • 长度为 \(n\)
  • 恰有 \(k\) 个数满足:所有包含这个数的区间中,不同的最大值的个数恰有 \(m\) 个。

答案对 \(p\) 取模。

\(1 \le n \le 100, 1 \le m \le n, 1 \le k \le n, 1 \le p \le 10^9\)


  动态规划 卡常

  虽然是个屑题,但是它很好。

  除了最后一步卡常,其他都想出来了。

  对于排列的 DP,比较经典的是维护已有的排列,然后在中间插入下一个数,但是在这里几乎无法计数。

  注意到题目的限制实际上是前缀的最大值个数 + 后缀最大值个数,于是可以想到单调栈,顺便想到笛卡尔树,于是问题转化为对于整个排列建立笛卡尔树后深度为 \(m\) 的节点共有 \(k\) 个的方案数,这个可以考虑 DP :

  记 \(f(l, r, t, v)\) 表示对于左端点为 \(l\),右端点为 \(r\) 的序列建立笛卡尔树,根节点深度为 \(t\),共有 \(v\) 个节点满足条件,转移的时候枚举最大值的位置,类似区间 DP + 背包处理即可,这样是 \(\mathcal O(n^6)\) 的,显然过不了,但是可以发现我们实际上不会关心区间的左右端点,只会关心区间长度,于是状态变为 \(f(len, t, v)\) 表示长度为 \(len\) 的区间,根节点深度为 \(t\),有 \(v\) 个节点满足条件的方案数,这样还是枚举最大值转移,复杂度 \(\mathcal O(n ^ 5)\)

  但还是过不了,甚至发现没有优化余地了,于是孩子弃疗了,点开了题解,发现题解也是 \(\mathcal O(n ^ 5)\) /yun。

  这个时候,我们发现, \(v \le \dfrac{len + 1}{2}\),记搜的时候加上剪枝即可,常数 \(\times \frac{1}{4}\),然后就可以过了。

  于是 \(\mathcal O(n ^ 5)\) 艹过 \(100\)

  代码

posted @ 2022-01-06 07:35  Werner_Yin  阅读(56)  评论(3编辑  收藏  举报