M-SOLUTIONS Programming Contest 2021

E

Rook Path
题目大意
给定一个 n×5n \times 5 的棋盘,有一个车,每一次必须移动,能够移动到当前所在的行的同一行任意一个位置
或者是当前所在列同一列的任意一个位置,起始时候在 (x1,y1)(x_1, y_1),移动 kk 步,问 kk 步后在 (x2,y2)(x_2, y_2)
有多少种可能性

不难想到是 dpdp,用移动的步数作为 dpdp 的阶段,不难列出状态转移方程如下
f(k,x,y)f(k, x, y) 表示当前第 kk 步,位于 (x,y)(x, y) 的方案数,则
f(k,x,y)=xxf(k1,x,y)+yyf(k1,x,y)\displaystyle f(k, x, y) = \sum_{x' \neq x} f(k-1, x', y) + \sum_{y' \neq y} f(k-1, x, y')

考虑优化,因为最后只与 x=x?y=y?x' = x? \quad y' = y? 有关,可以考虑状态压缩
00 表示 x=xx' = x11 表示 xxx' \neq x,同样 00 表示 y=yy' = y11 表示 yyy' \neq y
这样不难列出如下状态转移方程

dp(k,0,0)=dp(k1,1,0)+dp(k1,0,1)dp(k, 0, 0) = dp(k-1, 1, 0) + dp(k-1, 0, 1)
说明,此时 k1kk-1 \to k 过程中只能有一种移动方式,即同行或同列移动

dp(k,1,0)=dp(k1,0,0)(n1)+dp(k1,1,0)(n2)+dp(k1,1,1)dp(k,1, 0) = dp(k-1, 0, 0) \cdot (n-1) + dp(k-1, 1, 0) \cdot (n-2) + dp(k-1, 1, 1)
此时 kk 阶段所在的列 yy' 是确定的,k1kk-1 \to k 有两种情况,即在当前列移动,或者从其他列移动到当前列
从其他列移动到当前列,只有一种平移方式,即直接移动到 yy' 列,当前列移动呢?考虑 k1k-1 阶段能够选择的行有多少种?

dp(k,0,1)=dp(k1,0,0)(m1)+dp(k1,0,1)(m2)+dp(k1,1,1)dp(k, 0, 1) = dp(k-1, 0, 0) \cdot (m-1) + dp(k-1, 0, 1) \cdot (m-2) + dp(k-1, 1, 1)
和上一种情况完全对称

dp(k,1,1)=dp(k1,1,0)(m1)+dp(k1,0,1)(n1)+dp(k1,1,1)(n2+m2)dp(k, 1, 1) = dp(k-1, 1, 0)\cdot (m-1) + dp(k-1, 0, 1) \cdot (n-1) + dp(k-1, 1, 1) \cdot (n-2 + m-2)
k1k-1 阶段可能和 kk 阶段,同行不同列,从 (m1)(m-1) 列中任选一列作为状态,不同行同列,从 (n1)(n-1) 行任选作为状态
还有就是不同行,不同列,此时能选择行移动或者列移动,有 n2+m2n-2 + m-2 种选择

根据这 44 种情况 dpdp 即可,一开始时候 dp(0,0,0)=1dp(0, 0, 0) = 1dpdp 的终点是什么呢?
考虑 x2=x1?x_2 = x_1? 或者是 y2=y1?y_2 = y_1? 判断终点状态是 (0,0),(0,1),(1,0),(1,1)(0, 0), (0, 1), (1, 0), (1, 1) 哪一种
比如 xx 坐标对应的状态是 11,那么终点和起点行不同x2x_2 是这些不同状态中的任意一种,答案是 dp(1,)/(n1)dp(1,\cdots) / (n-1)
如果相同呢?那么行可以选择的情况只有 11 种,dp(0,)/1dp(0, \cdots) / 1yy 情况同理
用向量 vx={1,n1},vy={1,m1}\bm{vx} = \{1, n-1\}, \bm{vy} = \{1, m-1\},对于最后的状态 dp(i,j)dp(i, j)
返回 dp(i,j)/vx(i)/vy(j)dp(i, j) / \bm{vx}(i) / \bm{vy}(j) 即可,其中 i(x2=?x1)i \leftarrow (x_2 =? x_1)

F

Simple Operations on Sequence
题目大意
给定大小为 nn 的数组 A,BA, B,一次操作可以有如下两种
任意选择 AiA_i,让其 +1+1 或者 1-1,产生 XX 代价,或者是任意交换 AA 中的两个元素,产生 YY 代价
问需要最少的代价,使得 A,BA, B 相等

算法分析
首先对于 n18n \leqslant 18,不难想到是状态压缩,转移方程大致如下
假设当前处理第 ii 个数,其中前面 i1i-1 个数都相等,即 j[0i1]j \in [0\cdots i-1] 均有 Aj=BjA_j = B_j
此时加入 ii,令 Ai=BiA_i = B_i,有状态转移
dp(s(1i))=min(dp(s)+cost(Ai=Bi))dp(s \mid (1\ll i)) = \min \left(dp(s) + \textbf{cost}(A_i = B_i)\right)
难点在于 cost(Ai=Bi)\textbf{cost}(A_i = B_i) 怎么计算

注意代价有两部分组成

  • (A1,A2,,An)(Ap1,Ap2,,Apn)(A_1, A_2, \cdots, A_n) \to (A_{p_1}, A_{p_2},\cdots, A_{p_n}),这里转换的代价,实际上是排列
    P=(p1,p2,pn)P=(p_1, p_2, \cdots p_n) 逆序对的数目 inv(P)\textbf{inv}(P),这部分的代价为 inv(P)Y\textbf{inv}(P) \cdot Y
  • 还有一部分代价就是 i=1nApiBi\displaystyle\sum_{i = 1}^{n} |A_{p_i} - B_i|

算法设计
这里让 BB 数组不动,改变 AA 数组,用一个状态 ss 来表示,其中 ss 中为 11 的位 ii 表示
B(i)=A(pi)B(i) = A(p_i),即已经确定了 BiB_i 这一位AA对应的位 ApiA_{p_i} 相等
状态转移是 dp({000})dp({111})dp(\{00\cdots 0\}) \to dp(\{11\cdots 1\})

考虑某个状态 ss,尝试加入不在 ss 中的元素 xxdp(s)dp(s{x})dp(s) \longrightarrow dp(s \cup \{x\})

  • 首先计算 ss 中有多少个 11,不妨设有 jj11,说明已经确定了 (B1,B2,,Bj)(B_1, B_2, \cdots, B_j)
    当前正在确定 Bj+1B_{j+1},将 xx 加入 ss 集合的代价是 A(x)B(j+1)X|A(x)-B(j+1)| \cdot X
  • 考虑加入 xx 过程,AA 的下标 {{p1,p2,,pj},pj+1}{{p1,p2,,pj},x}\{\{p_1, p_2, \cdots, p_{j}\}, p_{j+1}\} \leftarrow \{\{p_1, p_2, \cdots, p_{j}\}, x\}
    那么代价要加上 A(1,2,j)A(p1,p2,pj)A(1, 2, \cdots j) \to A(p_1, p_2, \cdots p_j),实际上是计算 inv(P[1j])\text{inv}(P[1\to j])
    即前 jj 个数逆序对的个数,实际上,因为 PP 是一个排列,x{1n}x \in \{1\cdots n\},需要看一下
    ss下标 <x< x 的位,是不是都在 ss
    如果发现 ss 中的 pp 位为 00,并且 p<xp < x,那么逆序对的个数就 +1+1,最后算出此时的逆序对 inv(s,x)\text{inv}(s, x)
    代价要加上 inv(s,x)Y\text{inv}(s, x) \cdot Y
  • 状态转移方程如下,dp(s{x})minxs(dp(s)+inv(s,x)Y+AxBj+1X)dp(s\cup \{x\}) \longleftarrow \displaystyle\min_{x \notin s}\left(dp(s) + \text{inv}(s, x)\cdot Y + |A_x - B_{j+1}|\cdot X\right)
    其中,jjss11 的个数,表示当前已经确定了 B[1j]B[1\cdots j] 中所有元素,正在安排 Bj+1B_{j+1}

结论
如何计算一个排列 (1,2,,i)(p1,p2,x)(1, 2, \cdots, i) \to (p_1, p_2 \cdots, x) 的逆序对个数?
实际上遍历整个排列,如果比 xx 小的数都在 xx 前面,那么逆序对很显然是 00
逆序对的个数,实际上要统计 xx 之前(如果用一个集合维护的话,就是统计集合中)
有多少个数 <x< x 并且不在集合中

G

Modulo Shortest Path
题目大意,给定 nn 个点的完全图,给定 a[1n],b[1n]a[1\cdots n], b[1\cdots n],任意 i,j,iji, j, i \neq j
(ij)(i\to j) 的有向边,权值为 (ai+bj)modM(a_i + b_j) \bmod M,问从 1n1 \to n 的最短路径

如果直接在原图上跑 dijkstra\text{dijkstra},因为图的规模是 O(n2)O(n^2),必然会超时
注意到任意两点 i,ji, j 的权值总是在 MM剩余系中,考虑剩余系的值 {0,1,,M1}\{\overline{0}, \overline{1}, \cdots, \overline{M-1}\}
这样实际上只需要考虑 MM 个点即可
G

算法设计
可以考虑拆边,将长度为 MM 的边,依次拆成 01M100 \to 1 \to \cdots \to M-1 \to 0 的环,两点间的长度分别为 11
(i,j)=(Ai+Bj)modM(i, j) = (A_i + B_j) \bmod M,应该对应一张图 GG',其中从 ii 进入环上的某个点 p1\overline{p_1}
然后从 pr\overline{p_r} 处离开环,进入 jj

(Ai+Bj)modM=r(A_i + B_j) \bmod M = r,可以推出 Bj(Ai)+r (modM)B_j \equiv (-A_i) + r \ (\bmod M)
也就是说,如果令 p1=(AimodM)\overline{p_1} = (-A_i \bmod M),令边 (i,p1)(i, \overline{p_1}) 的权值为 00
又因为 Bj=(Ai+r)B_j = (\overline{-A_i} + r),也就是说 BjB_j 是在环上距离 Ai\overline{-A_i} 恰为 rr 的点
pr(BjmodM)\overline{p_r} \leftarrow (B_j \bmod M),并且令 (pr,j)(\overline{p_r}, j) 的权值为 00
原问题和图 GG' 恰好一一对应

再观察发现,我们根本用不到 MM 个点,实际上,只有 Ai(modM)\overline{-A_i}(\bmod M)Bi(modM)\overline{B_i}(\bmod M)
这些点是有意义的,离散化后将其放入集合 vv 中,按剩余系的值排序,然后按从小到大的顺序依次连边
离散化之后对应的原来剩余系的值rm(vi)\text{rm}(v_i)
新图中令 (vk,vk+1)(v_k, v_{k+1}) 的权值为 (rm[vk+1]rm[vk])(\textbf{rm}[v_{k+1}] - \textbf{rm}[v_k])
这样只有 O(2n)O(2n) 个点,可以直接 dijkstra\text{dijkstra}
另外注意图中剩余系是有环的,如果遍历到 vmv_{m} 最后一个元素,(假设 vv 中最后一个元素是 vmv_m
需要在 (vm,v0)(v_{m}, v_0) 之间连边,权值为 (M+rm[v0]rm[vm])modM(M + \textbf{rm}[v_0] - \textbf{rm}[v_{m}]) \bmod M

算法实现

  • 建一张新图 GG,用 get(x,type)\text{get}(x, type) 表示点 xx 对应在新图中点的编号,其中 type=0type = 0 表示原图中的点
    type=1type = 1 表示剩余系
  • 对每一个 aia_i,在 i(aimodM)i\longrightarrow \overline{(-a_i \bmod M)} 建一条有向边,权值为 00
    同理对每一个 bib_ibimodMi\overline{b_i \bmod M} \longrightarrow i 建一条有向边,权值为 00
    (aimodM)\overline{(-a_i \bmod M)}bimodM\overline{b_i \bmod M} 加入集合 vv 中并排序
    然后对集合 vv 中的元素按前面描述的方式,加入有向边
  • 对新图从 get(1,0)get(n,0)\text{get}(1, 0) \to \text{get}(n, 0)dijkstra\text{dijkstra} 即可