Skip to main content
  1. Posts/

LeetCode-2681 英雄的力量

·3 mins·

LeetCode-2681 英雄的力量 #

Solution 1 #

不要求序列连续, 所以可以先将数组排序, 以下讨论均基于排序后的 $nums$ . 考虑单个元素组成的序列, 这部分的值和为 $\sum_{0\leq i < n}nums^3[i]$ . 对于更多元素的序列, 假设最小值为 $nums[i]$ , 最大值为 $nums[j]$ , 那么一个序列的值为 $nums[i]\times nums^2[j]$ , 这样的序列有 $2^{j - i - 1}$ 个. 这部分的值和即为 $$ \sum_{0\leq i < j < n}nums[i]\times nums^2[j]\times 2^{j - i - 1} $$ 直接计算的话时间复杂度是 $O(n^2)$ , 考虑使用前缀和优化. 将上式改写为 $$ \sum_{0\leq i < n - 1}[\frac{nums[i]}{2^{i+1}}(\sum_{i < j < n}nums^2[j]\times 2^j)] \= \sum_{0\leq i < n - 1}[\frac{nums[i]}{2^{i+1}}(\sum_{0 < j \leq n - 1}nums^2[j]\times 2^j - \sum_{0 < j \leq i} nums^2[j]\times 2^j) ] $$ 可以使用 $O(n)$ 的时间预处理出 $\sum_{0\leq j \leq i}nums^2[j]\times 2^j$ , 从而可以在 $O(n)$ 的时间内计算出答案. 需要注意的是, 取模意义下的除法需要使用逆元进行处理.

using ll = long long;
const int MOD = 1e9 + 7;

class Solution {
public:
    // 快速幂
    ll power(ll x, ll n) {
        ll result = 1;
        while (n > 0) {
            if (n % 2 == 1) {
                result = (result * x) % MOD;
            }
            x = (x * x) % MOD;
            n /= 2;
        }
        return result;
    }

    // 逆元
    ll inverse(ll x) {
        return power(x, MOD - 2);
    }

    int sumOfPower(vector<int>& nums) {
        sort(nums.begin(), nums.end());
        int n = nums.size();
        vector<ll> sum(n, 0);
        for (int i = 0; i < n; i++) {
            sum[i] = ((nums[i] * 1LL) % MOD * nums[i] % MOD * power(2, i)) % MOD;
            if (i > 0) {
                sum[i] = (sum[i] + sum[i - 1]) % MOD;
            }
        }
        ll ans = 0;
        for (int i = 0; i < n - 1; i++) {
            ll coef = (nums[i] * 1LL * (sum[n - 1] - sum[i])) % MOD;
            coef = (coef * inverse(power(2, i + 1))) % MOD;
            ans = (ans + coef) % MOD;
        }
        for (int v : nums) {
            ans = (ans + ((v * 1LL * v) % MOD) * v) % MOD;
        }
        return ans >= 0? ans: ans + MOD;
    }
};

Solution 2 #

记 $dp[i]$ 为以 $nums[i]$ 为最大值 (也就是结尾) 的序列的最小值的和, 那么有 $$ dp[i] = nums[i] + \sum_{j = 0}^{i - 1}dp[j] $$ 目标即为 $$ \sum_{i = 0}^{n - 1}dp[i]\times nums^2[i] $$

using ll = long long;
const int MOD = 1e9 + 7;
class Solution {
public:
    int sumOfPower(vector<int>& nums) {
        int n = nums.size();
        sort(nums.begin(), nums.end());
        int dp = 0, preSum = 0; 
        int res = 0;
        for (int i = 0; i < n; i++) {
            dp = (nums[i] + preSum) % MOD;
            preSum = (preSum + dp) % MOD;
            res = (int) ((res + (ll) nums[i] * nums[i] % MOD * dp) % MOD);
            if (res < 0) {
                res += MOD;
            }
        }
        return res;
    }
};