Sum of Subsequence Widths

hard math sorting combinatorics

Problem

The width of a sequence is the difference between its maximum and minimum element. Given an array of integers nums, return the sum of the widths of all non-empty subsequences of nums. Because the answer can be very large, return it modulo 109 + 7.

Inputnums = [2, 1, 3]
Output6
The subsequences are [1],[2],[3],[2,1],[2,3],[1,3],[2,1,3] with widths 0,0,0,1,1,2,2 → total 6. Order inside a subsequence does not matter for the width.

def sum_subseq_widths(nums):
    MOD = 10**9 + 7
    nums.sort()
    n = len(nums)
    ans = 0
    pow2 = 1                      # 2^i, starts at 2^0
    for i in range(n):
        # nums[i] is the max of 2^i subsets, the min of 2^(n-1-i)
        ans = (ans + (pow2 - pow(2, n - 1 - i, MOD)) * nums[i]) % MOD
        pow2 = pow2 * 2 % MOD
    return ans % MOD
function sumSubseqWidths(nums) {
  const MOD = 1000000007n;
  nums.sort((a, b) => a - b);
  const n = nums.length;
  // precompute powers of two mod MOD
  const pow = new Array(n);
  pow[0] = 1n;
  for (let i = 1; i < n; i++) pow[i] = pow[i - 1] * 2n % MOD;
  let ans = 0n;
  for (let i = 0; i < n; i++) {
    const w = (pow[i] - pow[n - 1 - i] + MOD) % MOD;
    ans = (ans + w * BigInt(nums[i])) % MOD;
  }
  return Number((ans % MOD + MOD) % MOD);
}
class Solution {
    public int sumSubseqWidths(int[] nums) {
        long MOD = 1_000_000_007L;
        Arrays.sort(nums);
        int n = nums.length;
        long[] pow = new long[n];
        pow[0] = 1;
        for (int i = 1; i < n; i++) pow[i] = pow[i - 1] * 2 % MOD;
        long ans = 0;
        for (int i = 0; i < n; i++) {
            long w = (pow[i] - pow[n - 1 - i] + MOD) % MOD;
            ans = (ans + w * nums[i]) % MOD;
        }
        return (int) ((ans % MOD + MOD) % MOD);
    }
}
int sumSubseqWidths(vector<int>& nums) {
    const long long MOD = 1000000007LL;
    sort(nums.begin(), nums.end());
    int n = nums.size();
    vector<long long> pw(n);
    pw[0] = 1;
    for (int i = 1; i < n; i++) pw[i] = pw[i - 1] * 2 % MOD;
    long long ans = 0;
    for (int i = 0; i < n; i++) {
        long long w = (pw[i] - pw[n - 1 - i] + MOD) % MOD;
        ans = (ans + w * nums[i]) % MOD;
    }
    return (int) ((ans % MOD + MOD) % MOD);
}
Time: O(n log n) Space: O(n)