Part1. 题目概述
你有一个数组,其顺序可以随意打乱。
你可以在其中任选一个数增加 $k$,这记为一次操作。
求最小的操作次数以使原数组为回文串。
若不可能,输出 $-1$。
Part2. 思路
首先看到只能增加 $k$,说明无论怎么操作,每个数除以 $k$ 的余数不变。
要求得到回文串且顺序可以随意打乱,也就是说只要满足最终的数组只有不大于一个数出现的次数为奇数(这个数拿一个放中间,其他的左右两边对称放)。
再回到1,除以 $k$ 的余数不变,那么可以对除以 $k$ 的每一个余数分组,每一组都可以通过加 $k$ 使得数字相等,比如这组样例的分组:
1
213 3
2 3 9 14 17 10 22 20 18 30 1 4 28余数为 $0$ 余数为 $1$ 余数为 $2$ $3,9,18,30$ $10,22,1,4,28$ $2,14,17,20$ 如何判断是否可行呢?只需要统计所有组中有几组的元素个数为奇数(如上面的分组中余数为 $1$ 组就是奇数个数,必须把这个组中的某个元素放到新序列的中心位置),如果个数大于 $1$,就一定是不可行的(不可能把多个元素放到中心)。
接下来开始构造最优解。可以很清楚地发现,要在每一组中构造出相等的元素对(一个放前面,一个放后面),比如上余数为 $1$ 组可以这样构造:
$$(2,14),(17,20)$$
只要:
$$(2+3\times4,14),(17+3\times1,20)$$
进行了 $4+1=5$ 次操作。如果是奇数个元素的组,只需要取出一个元素放在中心后,变成偶数个元素的组即可。
如何使解最优呢?可以先尝试把每一个组内排个序:
余数为 $0$ 余数为 $1$ 余数为 $2$ $3,9,18,30$ $1,4,10,22,28$ $2,14,17,20$ 这时候要分类讨论一下了:
一组中有偶数个元素。
从小到大,每次取两个,一定最优。(否则如果跨过中间的元素找,一定会需要更多操作,你可以自己模拟一下)。
一组中有奇数个元素。
很快想到朴素方法:枚举要去除的元素,求出去除每个元素下的最优,时间复杂度 $O(n^2)$。
这显然会超时,但大致思路是可行的,求出下一个解时很多计算是和上一个重复的,这就有了优化的方法。下图七个数的情况:
不取 第一组 第二组 第三组 $1$ $(2,3)$ $(4,5)$ $(6,7)$ $2$ $\color{red}(1,3)$ $(4,5)$ $(6,7)$ $3$ $\color{red}(1,2)$ $(4,5)$ $(6,7)$ $4$ $(1,2)$ $\color{red}(3,5)$ $(6,7)$ $5$ $(1,2)$ $\color{red}(3,4)$ $(6,7)$ $6$ $(1,2)$ $(3,4)$ $\color{red}(5,7)$ $7$ $(1,2)$ $(3,4)$ $\color{red}(5,6)$ 红色的就是变化的部分,这样就解出了(分奇偶讨论一下)。
$$f(a_{i+1})= \begin{cases}f(a_i)-\dfrac{(a_{i+2}-a_{i+1})}{k}+\dfrac{(a_{i+2}-a_i)}{k},\quad &&i \equiv 1 \pmod 2\f(a_i)-\dfrac{(a_{i+1}-a_{i-1})}{k}+\dfrac{(a_{i}-a_{i-1})}{k},\quad&&i \equiv 0 \pmod 2\end{cases} $$
问题解决!
Part3. Code
注意数据范围,存余数等可以开映射解决,也可以离散化。
1 |
|