[2021 Summer Petrozavodsk Camp, Day 3: IQ test] J. Joke

[2021 Summer Petrozavodsk Camp, Day 3: IQ test] J. Joke

题目描述

你有两个 \(1\)\(n\) 的排列 \(p\)\(q\)。我们想在一个 \(2 \times n\) 的矩阵 \(a\) 中填入 \(1\)\(2n\) 的排列,满足:

  • 对于所有的 \(i\)\(j\)\(a_{1,i} < a_{1,j} \iff p_i < p_j\)
  • 对于所有的 \(i\)\(j\)\(a_{2,i} < a_{2,j} \iff q_i < q_j\)

通过对矩阵 \(a\) 的填数,我们能得到一个长度为 \(n\)\(01\)\(s\),当 \(a_{1,i} < a_{2,i}\) 时,\(s_i = 0\),否则 \(s_i = 1\)

对于两个排列 \(p\)\(q\),定义 \(f(p,q)\) 表示通过在矩阵中填数,能得到的不同的 \(s\) 串的个数。

现在给你 \(p\) 这个排列中的所有元素,和 \(p\) 这个排列中的一些元素,\(q\) 中剩下元素都是不确定的。对于所有满足条件的 \(q\)\(f(p,q)\) 的和是多少。由于答案很大,输出对 \(998244353\) 取模的答案。


思路

因为函数 \(f(p, q)\) 的值取决于 \((p_i, q_i)\) 的顺序, 和序列 \(p, q\) 之间的顺序无关, 我们可以先以 \(p\) 序列为关键字排序.

给出一个性质: \(f((1, 2, \dots, n), q)\) 的值等于 \(q\) 中上升子序列的数量.

  • 证明

    首先来分析一下字符串 \(s\) 满足 \(p\)\(q\) 的条件. 我们将矩阵看做上面和下面分别 \(n\) 个点的有向图, 每一条边 \((u, v)\) 表示点 \(u\) 填的数字小于点 \(v\) 填的数字. 容易发现 \(s\) 合法当且仅当原图是一个 \(\rm{DAG}\), 也就是没有环, 稍加分析可以得知这个条件同时等价于不包含长度为 \(4\) 的环.

    现在我们来看 \(q_i = n\) 的位置:

    1. 如果 \(s_i = 0\), 即 \(a_{1, i} < a_{2, i}\), 那么该图的部分连边会如下图所示

      pVCylnI.png

      可以发现这样对于这个位置是一定不会产生环的, 我们忽略它.

    2. \(s_i = 1\), 则 \(a_{1, i} > a_{2, i}\), 也即 \(a_{1, i}\) 大于第 \(2\)最大的数字, 同时对于所有 \(j > i\) 都有 \(a_{1, j} > a_{2, j}\), 否则就会产生环.

    综上所述, 我们一共有 \(2\) 种操作

    • 删除掉最大的元素.
    • 删除掉最大的元素及其右边所有的元素.

    可以证明, 通过这些操作逐步删除整个序列 \(q\) 的方式数等于 \(q\) 的递增子序列数量. 因为每次操作 \(2\) 对应选择一个最大元素及其右侧元素, 形成一个递增子序列.

有了上面的性质, 如果序列 \(q\) 已知, 那么就可以在 \(\mathcal{O}(n \log n)\) 的时间内计算出答案了.

现在来看不知道 \(q\) 的情况. 我们定义 \(f_{i, j, k}\) 表示在序列 \(q\) 中当前枚举到第 \(i\) 位, 当前位填 \(k\), 「当前上升子序列」中一共有 \(j\) 个未知的位置的方案数.

转移的话分两种

\[f_{i, j, k} = \begin{cases} \begin{align*} &\sum_{i' < i} \sum_{k' < k} f_{i', j - 1, k'} & q_i = 0 \\ &\sum_{i' < i} \sum_{k' < k} f_{i', j, k'} & q_i \ne 0 \end{align*} \end{cases} \]

转移可以使用前缀和优化做到 \(\mathcal{O}(n^3)\).

\(q\) 中有 \(num\) 个位置为 \(0\), 那么最后答案即 \(\displaystyle \sum_i \sum_j \sum_k f_{i, j, k} \times (num - j)!\)​.

posted @ 2025-06-03 20:28  Steven1013  阅读(18)  评论(0)    收藏  举报