ABC134F Permutation Oddness
Problem Statement
Let us define the oddness of a permutation \(p = \\{p_1, p_2, \dots, p_n\\}\) of \(\\{1, 2, \dots, n\\}\) as \(\sum_{i=1}^{n} | i - p_i |\). Find the number of permutations of \(\\{1, 2, \dots, n\\}\) of oddness \(K\), modulo \(10^9+7\).
Constraints
- \(1 \le n \le 50\)
- \(1 \le K \le n^2\)
Observation ①
\(\sum_{i = 1}^{n} p_i - i = 0\) \(\implies\) \(\sum_{i = 1}^{n} | p_i - i |\) 是偶数。
进一步有 \(\sum_{p_i > i} p_i - i = \sum_{p_i < i} i - p_i = \dfrac{\sum_{i = 1}^{n} | p_i - i |}{ 2}\)
Approach
以下内容参考了题解 http://kazune-lab.net/contest/2019/07/20/abc134/ 。
左边的圆形代表数字,右边的方形代表盒子,方形右边的数字是盒子的编号。箭头表示将数字放入盒子中。将 \(p_i\) 看成数字 \(i\) 所在的盒子的编号。
Observation ②
\(|p_i - i|\) = 连接数字 \(i\) 与盒子 \(p_i\) 的线与 \(n - 1\) 条水平虚线 \(\ell_1, \ell_2, \dots, \ell_{n-1}\) 的交点数目。
以上图为例,\(n = 5\),共有四条水平虚线。
令 \(a_j\) 表示连接 \(i\) 与 \(p_i\) 且 \(i < p_i\) 的那些线与第 \(j\) 条水平虚线 \(\ell_j\) 的交点个数。
以上图为例,满足条件的线有三条(即加粗的那三条线),\(a_1 = 1, a_2 = 2, a_3 = 2, a_4 = 1\) 。
Observation ③
\(\sum_{i = 1}^{n - 1} a_i = \sum_{i < p_i} p_i - i = \dfrac{\sum_{i = 1}^{n} | p_i - i |}{ 2}\)
可以把往盒子里放数字的过程看作下述 \(n\) 阶段决策过程。笼统地说,在第 \(i\) 个阶段考虑数字 \(i\) 和编号为 \(i\) 的盒子如何处置。
把在阶段 \(i\) 完成之后 \(1, 2, \dots, i\) 这些数字中尚未确定要放进哪个盒子的那些数字的集合记作 \(S\),初始时 \(S\) 为空。
阶段 \(i\) 由下述伪代码所描述:
\(\mathtt{if}\) 要把 \(i\) 放进 \(i\) 号盒子
\(\qquad\) 把 \(i\) 放进 \(i\) 号盒子
\(\mathtt{elif}\) \(S \ne \emptyset\)
\(\qquad\mathtt{if}\) 要把 \(i\) 放到某个编号小于 \(i\) 的盒子
\(\qquad\qquad\) 确定把 \(i\) 放进哪个盒子并把 \(i\) 放进去
\(\qquad\mathtt{else}\)
\(\qquad\qquad\) 把 \(i\) 加入 \(S\)
\(\qquad\mathtt{if}\) 要把 \(S\) 中的某个数放进盒子 \(i\)
\(\qquad\qquad\) 选一个数放进盒子 \(i\) 并将其从 \(S\) 中删除
\(\mathtt{else}\)
\(\qquad\) 把 \(i\) 加入 \(S\)
以三元组 \((i, j, k)\) 表示第 \(i\) 个阶段结束后的状态:
- \(j := |S|\)(即 \(1\) 到 \(i\) 这些数中有 \(j\) 个要放到编号大于 \(i\) 的盒子里)
- \(k := \sum_{t = 1}^{i} a_t\) 。
当阶段 \(i\) 结束时,\(i\) 以后的数字怎么安排尚未考虑,\(j\) 个要放在编号大于 \(i\) 的盒子里的数字具体怎么放也没确定。
我们感兴趣的最终状态是 \((n, 0, K / 2)\) 。
注:上图中并未画出第 \(n\) 条水平虚线 \(\ell_n\),因为只有最终状态是 \((n, 0, \cdot)\) 才对应于一个排列,此时必有 \(a_n = 0\)。
以上图的放置过程为例,状态依次是
\((0, 0, 0) \to (1, 1, 1) \to (2, 2, 3) \to (3, 2, 5) \to (4, 1, 6) \to (5, 0, 6)\)
状态转移
\((i, j, k) \to (i + 1, j', k')\)
- 把 \(i + 1\) 放进 \(i + 1\) 号盒子:\((i + 1, j, k + j)\)
- \(j > 0\),把 \(i + 1\) 放进 \(x\) 号盒子(\(x \le i\)): \((i + 1, j, k + j)\)
- \(j > 0\),把 \(S\) 中的某个数放进 \(i\) 号盒子:\((i + 1, j, k + j)\)
- \(j > 0\),把 \(i + 1\) 放进 \(x\) 号盒子(\(x \le i\))并把 \(S\) 中的某个数放进 \(i\) 号盒子:\((i + 1, j - 1, k + j - 1)\)
- \(S\) 中的数以及 \(i+1\) 所在的盒子编号都大于 \(i + 1\):\((i + 1, j + 1, k + j + 1)\)