传送门

T4. 搬砖

给定 \(n\) 个非负整数 \(a_i\),每次可以花费 \(1\) 的代价使得一个数字加 \(1\) 或者减 \(1\)(不能被减到负数),问最少需要多少代价使得所有数字的异或值为 \(0\)

要求多测

限制:

  • 对于 \(5\%\) 的数据:\(n=2, a_i \leqslant 10^9\)
  • 对于另外 \(10\%\) 的数据:\(n \leqslant 5\)\(a_i \leqslant 30\)
  • 对于另外 \(15\%\) 的数据:\(n \leqslant 15\)\(a_i \leqslant 10^3\)
  • 对于另外 \(20\%\) 的数据:\(n \leqslant 8\)\(a_i \leqslant 10^9\)
  • 对于另外 \(15\%\) 的数据:\(n \leqslant 10\)\(a_i \leqslant 10^9\)
  • 对于所有数据:\(1 \leqslant T \leqslant 6, 1 \leqslant n \leqslant 15, 0 \leqslant a_i \leqslant 10^9\)

参考难题:蓝

算法分析

下文中,假定 \(m = \max(a_i)\)

\(5\) 分:

此时 \(n = 2\),问题变为了使得两数相等的最小代价,输出两数的差值即可。

\(15\) 分(另外 \(10\%\) 的数据):

此时 \(n \leqslant 5\)\(a_i \leqslant 30\),考虑直接 \(dfs\) 暴力枚举每个 \(a_i\) 的最终取值 \(a_i'\),那么对于每一种情况所需要付出的代价就是 \(|a_i - a_i'|\) 之和,即 \(\sum |a_i - a_i'|\) 。取所有情况中的最小代价即可,时间复杂度为 \(O(m^n)\)

\(30\) 分(另外 \(15\%\) 的数据):

此时 \(n \leqslant 15\)\(a_i \leqslant 10^3\),原问题是“使得 \(n\) 个数字的异或值为 \(0\)”,那么当我们枚举了 \(a_n\) 的最终取值 \(a_n'\) 之后,问题变为了“使得前 \(n-1\) 个数字的异或值为 \(a_n'\)”。不难发现这是一个子问题,因此可以考虑动态规划。

定义 dp[i][j] 表示使得前 \(i\) 个数字的异或值为 \(j\) 的最小代价,枚举 \(im, j\) 后,再枚举 \(k\) 表示当前第 \(i\) 个数字的最终取值,那么可以得到转移方程:

\[dp[i][j] = \min(dp[i][j], dp[i-1][j \oplus k] + |a_i-k|) \]

最终的答案为 \(dp[n][0]\),总时间复杂度为 \(O(nm^2)\)