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\)。
那么将转移方程写出来:
换一下:
注意到我们 \(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)\)。

浙公网安备 33010602011771号