1799. N 次操作后的最大分数和
题目:
给你?nums?,它是一个大小为?2 * n?的正整数数组。你必须对这个数组执行 n?次操作。
在第?i?次操作时(操作编号从 1?开始),你需要:
选择两个元素?x 和?y?。 获得分数?i * gcd(x, y)?。 将?x?和?y 从?nums?中删除。 请你返回 n?次操作后你能获得的分数和最大为多少。
函数?gcd(x, y)?是?x 和?y?的最大公约数。
示例 1:
输入:nums = [1,2] 输出:1 解释:最优操作是: (1 * gcd(1, 2)) = 1
示例 2:
输入:nums = [3,4,6,8] 输出:11 解释:最优操作是: (1 * gcd(3, 6)) + (2 * gcd(4, 8)) = 3 + 8 = 11
示例 3:
输入:nums = [1,2,3,4,5,6] 输出:14 解释:最优操作是: (1 * gcd(1, 5)) + (2 * gcd(2, 4)) + (3 * gcd(3, 6)) = 1 + 4 + 9 = 14
提示:
1 <= n <= 7 nums.length == 2 * n 1 <= nums[i] <= 106
来源:力扣(LeetCode) 链接:https://leetcode.cn/problems/maximize-score-after-n-operations 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
代码:
class Solution {
public:
int maxScore(vector<int>& nums) {
int m = nums.size();
int g[m][m];
for (int i = 0; i < m; ++i) {
for (int j = i + 1; j < m; ++j) {
g[i][j] = gcd(nums[i], nums[j]);
}
}
int f[1 << m];
memset(f, 0, sizeof f);
for (int k = 0; k < 1 << m; ++k) {
int cnt = __builtin_popcount(k);
if (cnt % 2 == 0) {
for (int i = 0; i < m; ++i) {
if (k >> i & 1) {
for (int j = i + 1; j < m; ++j) {
if (k >> j & 1) {
f[k] = max(f[k], f[k ^ (1 << i) ^ (1 << j)] + cnt / 2 * g[i][j]);
}
}
}
}
}
}
return f[(1 << m) - 1];
}
};
/*
作者:lcbin
链接:https://leetcode.cn/problems/maximize-score-after-n-operations/solution/by-lcbin-8uxm/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
*/
注:
1.__builtin_popcount函数
该函数是C++自带的库函数,内部实现是用查表实现的。 作用:统计数字在二进制下“1”的个数。
|