目录
题目描述
思路解析
我们不妨先从简单的例子入手。
以示例1为主。我们知道 [1, 2, 4] 的答案与 [2, 1, 4] 是等价的,因为它们的子序列是完全一致的。
同时 [1, 2, 4] 也跟方面我们的表达式计算,因为我们花费更小的力气去寻找最大最小值。
我们给出运算模拟。
第一组:[1] = 1;
第二组:[2] = 8;
第三组:[1, 2] = 4;
第四组:[4] = 64;
第五组:[1, 4] = 16;
第六组:[2, 4] = 32;
第七组:[1, 2, 4] = 16;
总计:141.
如果我们按照颜色划分,也就是当我们逐一扫描加入元素的过程。
我们会发现,绿色组就是 { ,黄色组 } + {2}
同时,我们发现绿色组的英雄力量就是 (黄色组_min_sum + 2)* 4 = 12;
同理,蓝色组 = (绿色组_min_sum + 黄色组_min_sum + 4)* 16 = (3 + 1 + 4)* 16 = 128;
在这个表达式中,我们很快发现了前缀和的迹象。所以,我们自然而然能想到使用前缀和维护。
注意这个前缀和是每一个小组的最小值和的前缀和。
如果我们记录 dp[i] 为第 i 组的最小和,那么有公式
我们记 preSum[i] =
那么 preSum[i + 1] = preSum[i] + dp[i];
至此这道题就解析完成了。
AC代码
class Solution {
public:
int sumOfPower(vector<int>& nums) {
int n = nums.size();
sort(nums.begin(), nums.end());
vector<int> dp(n); //最小和
vector<int> preSum(n + 1); //最小和前缀
int res = 0, mod = 1e9 + 7;
for (int i = 0; i < n; i++) {
dp[i] = (nums[i] + preSum[i]) % mod;
preSum[i + 1] = (preSum[i] + dp[i]) % mod;
res = (int) ((res + (long long) nums[i] * nums[i] % mod * dp[i]) % mod);
if (res < 0) {
res += mod;
}
}
return res;
}
};