LeetCode 891. Sum of Subsequence Widths (找规律)

Given an array of integers A, consider all non-empty subsequences of A.

For any sequence S, let the width of S be the difference between the maximum and minimum element of S.

Return the sum of the widths of all subsequences of A.

As the answer may be very large, return the answer modulo 10^9 + 7.

Example 1:

Input: [2,1,3]
Output: 6
Explanation:
Subsequences are [1], [2], [3], [2,1], [2,3], [1,3], [2,1,3].
The corresponding widths are 0, 0, 0, 1, 1, 2, 2.
The sum of these widths is 6.

Note:

  • 1 <= A.length <= 20000
  • 1 <= A[i] <= 20000

解法
由题意易得,数组的顺序是可以改变的,因此先把数组排好序在处理会简单一点。
本来是直接计算,没有算出公式,得到了TLE,后来把递归公式给算一下,就AC了。
(还要注意溢出,因此用unsigned long long稳妥)

class Solution {
    const unsigned long long mod = 1000000007;
    unsigned long long Fn[20005]; /*Fn[i] = 2^(i-1) */
    unsigned long long Sumn[20005]; /* 2^0+2^1+...+2^n = 2^(n+1)-1 */
public:
    int sumSubseqWidths(vector<int> A) {
        sort(A.begin(), A.end());
        Fn[1] = 1;
        for(int i=2;i<=20002;i++) {
            Fn[i] = (Fn[i-1]<<1)%mod;
        }
        for(int i=0;i<=20000;i++) {
            Sumn[i] = Fn[i+2]-1;
        }

        ssize_t n = A.size();
        vector<unsigned long long> res(n+1, 0);
        unsigned long long ans = 0;
        /* native method will get TLE
        for(int i=2;i<=n;i++) {
            unsigned long long tmp = 0;
            for(int j=i-1;j>=1;j--) {
                int diff = A[i-1] - A[j-1];
                tmp += (res[j] + (Fn[j] * diff)%mod)%mod;
                tmp %= mod;
            }
            res[i] = tmp;
            ans = (ans+tmp)%mod;
        }
        */
        for(int i=2;i<=n;i++) {
            res[i] = (2*res[i-1] + Sumn[i-2]*(A[i-1]-A[i-2]))%mod;
            ans = (ans+res[i])%mod;
        }
        return ans;
    }
};

你可能感兴趣的:(算法,LeetCode,数学)