1
有一个长度为 nnn 的排列 aaa,其中有一些位置被替换成了 -1。你需要尝试恢复这个排列,将 -1 替换回数字。求有多少种可行的替换方法,满足得到的是一个排列,且不存在 ai=ia_i = iai=i 的。
n≤5000n\leq 5000n≤5000
前置技巧:一个每行、每列只有一个棋子的棋盘,任意交换行列,得到的棋盘每行、每列只有一个棋子。
在序列里填排列,某些位置有限制。想到把问题转化为在 n∗nn*nn∗n 的棋盘上填放棋子,对角线不能放,有些格子已经放了。我们把已经放石子的行、列删除,就变成了在一个棋盘上有若干个点不能放,且每行每列最多只有一个限制。容易发现我们并不关心限制的位置,因此可以强制通过行列交换使得限制为对角线上的一个前缀。设 f[i][j]f[i][j]f[i][j] 表示 i∗ii*ii∗i 的棋盘里有 jjj 个限制的方案数,那么考虑 f[i][j]f[i][j]f[i][j] 比 f[i][j−1]f[i][j-1]f[i][j−1] 少了那些状态,就是那些 (j,j)(j,j)(j,j) 放了石子的状态。因此 f[i][j]=f[i][j−1]−f[i−1][j−1]f[i][j]=f[i][j-1]-f[i-1][j-1]f[i][j]=f[i][j−1]−f[i−1][j−1]。
2
给定自然数n、k、x,你要求出第k小的长度为n的逆序对对数为x的1~n的排列。
考虑逐位确定这个排列。假设 1…i−11\dots i-11…i−1 都已经填好,我们要确定第 iii 个数填什么。枚举一个数 jjj,我们想要知道如果这一位填 ≤j\le j≤j 的数后面随便填的合法排列数量记为 sumjsum_jsumj,如果 sumj<ksum_j< ksumj<k 并且 sumj+1≥ksum_{j+1}\ge ksumj+1≥k,那么这一位就填 jjj。
发现枚举了一个数以后已经填数的部分逆序对数已知,我们要求的就是“ iii 个数的排列里逆序对数量为 jjj 的有多少个”。显然可以 dp 出来。