CF2124F2

题目大意:

你有一个数组 \(a\),一开始 \(a\) 是空的,你想进行若干次操作,问当 \(a\) 的长度为 \(n\) 时有多少可能的状态。
操作如下,选择两个整数 \(r \le s\),并将 \([r,r+1\sim s,1,2 \sim r - 1]\) 拼到 \(a\) 后面。
但还有 \(m\) 个条件,第 \(i\) 个条件给定 \(x,val\),表示 \(a_{x} \ne val\)
\(n,m \le 5000\)

解题思路:

这种创造数列的题要先想想如何构成双射,发现若干个不同的操作方式肯能会得到相同的 \(a\),考虑如何去钦定每个数列恰好被算一次。

考虑先贪心地划分,如果当前数不等于 \(1\),那么就通过找到下一个为 \(1\) 的位置,那么从这个 \(1\) 开始 \(val - 1\) 个数和当前数都必须在一起。
但如果当前数是 \(1\) 的话就不能确定,反例就是 \([1,2 \sim k, k + 1, k + 2 \sim m, 1,2 \sim k]\)

这样就相当于说前面有一个 \(1 \sim r - 1\) 的排列,然后后面拼上了 \([r,r+1\sim s,1,2 \sim r - 1]\)

所以我们考虑钦定它如果前面的是一个 \(r\) 排列,那么后面的第一个数不能是 \(r + 1\)
直接设 \(dp_{i,j}\) 表示前面 \(i\) 个数,最后一个是 \(j\) 排列,当 \(j = 0\) 时不是任意一个排列的方案数。

考虑枚举下一段的 \(r,s\),暴力判断即可做到 \(O(n^5)\),随便预处理即可做到 \(O(n^4)\),可以通过 \(F1\)

这种 \(dp\) 在转移的时候,记得填表刷表都试试。
考虑转移的时候枚举上一段是什么。

由于我们的状态已经钦定了上一段是什么,所以当 \(j \ne 0\) 的时候可以直接设 \(sum_{i} = \sum_{j = 0}^{n} dp_{i,j}\) 来优化到 \(O(1)\) 转移。

\(cnt_{x,y}\) 表示 \(a_{x} = y\) 时,有多少个 \(i < x\) 不能满足 \(a_{i} - i = a_{x} - x\)

那么将转移方程写出来:

\[dp_{i,j} = \sum_{r = 2}^{i} \sum_{s = r}^{i} [cnt_{i,r - 1} = 0 \wedge cnt_{i - s,r - 1} = cnt_{i - r + 1,s}] \times (sum_{i - s} - dp_{i - s, r - 1}) \]

换一下:

\[dp_{i,j} = \sum_{r = 1}^{i - 1} \sum_{s = r + 1}^{i} [cnt_{i,r} = 0 \wedge cnt_{i - s,r} = cnt_{i - r,s}] \times (sum_{i - s} - dp_{i - s, r}) \]

\[dp_{i,j} = \sum_{r = 1}^{i - 1} [cnt_{i,r} = 0] \sum_{s = r + 1}^{i} [cnt_{i - s,r} = cnt_{i - r,s}] \times (sum_{i - s} - dp_{i - s, r}) \]

注意到我们 \(cnt_{i,j} = cnt_{i - 1,j - 1} + 1\),所以对于每个 \(dp_{i,j}\),他能贡献的一定是区间。
\(O(n^2)\)

这样的做法是较为直觉的,但我们注意到在本题中那个数字 \(1\) 是特殊的,并且他是这两个等差数列的后面的开头。

所以考虑 \(f_{i,j}\) 表示 \(i \sim n\)\(i\)\(j > 1\),然后 \(g_{i,j}\) 表示 \(i \sim n\)\(a_{i} = 1\),且以 \(i\) 为开头的排列长度为 \(j\) 的方案数。

这两个都是好转移的。

\(O(n^2)\)

posted @ 2025-11-28 16:24  positive_deviation  阅读(0)  评论(0)    收藏  举报