[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\) 的位置:
-
如果 \(s_i = 0\), 即 \(a_{1, i} < a_{2, i}\), 那么该图的部分连边会如下图所示
可以发现这样对于这个位置是一定不会产生环的, 我们忽略它.
-
\(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\) 个未知的位置的方案数.
转移的话分两种
转移可以使用前缀和优化做到 \(\mathcal{O}(n^3)\).
设 \(q\) 中有 \(num\) 个位置为 \(0\), 那么最后答案即 \(\displaystyle \sum_i \sum_j \sum_k f_{i, j, k} \times (num - j)!\).


浙公网安备 33010602011771号