2681.英雄的力量
题目描述:
给你一个下标从 0 开始的整数数组 nums
,它表示英雄的能力值。如果我们选出一部分英雄,这组英雄的 力量 定义为:
i0
,i1
,…ik
表示这组英雄在数组中的下标。那么这组英雄的力量为max(nums[i0],nums[i1] ... nums[ik])2 * min(nums[i0],nums[i1] ... nums[ik])
。
请你返回所有可能的 非空 英雄组的 力量 之和。由于答案可能非常大,请你将结果对 109 + 7
取余。
数据范围:
$1\le nums.len \le 10^5,1\le nums[i] \le 10^9$
题解:
这个题目和子数组还不太一样,子数组的话就不能排序了。
这个题可以直接排序。如果是排序之后求子数组的,那就非常简单,直接前缀和就能得到。
但是这个是组合,组合与次序无关,可以排序,排序之后考虑针对某一个起点的贡献。
假如考虑 $a_i$ ,那么 $a_i$ 作为最小值,贡献为 $a_i \times (a_i^2 + a_{i + 1} ^ 2 + 2^1 \times a_{i + 2}^2 + 2^2 \times a_{i + 3}^2 + \cdots + 2^{j - i} \times a_{j}^2)$
为什么与 $2^i$ 有关呢,因为如果确定了起点 $a_i$ ,终点 $a_j$ ,那么中间的元素取与不取都是可以的,所以是中间元素的所有的子集。
观察该式子,发现后面一段可以递推得到,也就是 $a_{i + 1} ^ 2 + 2^1 \times a_{i + 2}^2 + 2^2 \times a_{i + 3}^2 + \cdots + 2^{j - i} \times a_{j}^2)$ 。前面的 $a_i^2$ 可以每次处理到的时候再加。因此可以使用一个 $sum$ 维护后面一段的和,然后从后往前,每次 $sum \times 2 + a_{i + 1}^2$ ,最后需要把 $a_i^2$ 加进去,然后乘以 $a_i$ 。
同样也可以枚举终点,然后求关于起点的递推式。
代码:
1 | auto optimize_cpp_stdio = []() |