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[n][0]\),总时间复杂度为 \(O(nm^2)\) 。