Advertisement

Range Product Queries of Powers - LeetCode 2438 Solution

Range Product Queries of Powers - Complete Solution Guide

Range Product Queries of Powers is LeetCode problem 2438, a Medium level challenge. This complete guide provides step-by-step explanations, multiple solution approaches, and optimized code in python3, java, cpp, c.

Problem Statement

Given a positive integer n , there exists a 0-indexed array called powers , composed of the minimum number of powers of 2 that sum to n . The array is sorted in non-decreasing order, and there is only one way to form the array. You are also given a 0-indexed 2D integer array queries , where queries[i] = [left i , right i ] . Each queries[i] represents a query where you have to find the product of all powers[j] with left i <= j <= right i . Return an array answers , equal in length to queries , w

Detailed Explanation

The problem asks us to find the product of powers of 2 within specified ranges. Given an integer `n`, we first decompose it into the minimum number of powers of 2. For example, if `n = 15`, the powers of 2 are `[1, 2, 4, 8]` (1 + 2 + 4 + 8 = 15). Then, given a set of queries, where each query `[left, right]` represents a range within the powers array, we calculate the product of the powers within that range. Since the product can be very large, we need to return the result modulo `10^9 + 7`.

Solution Approach

The solution involves three main steps: 1) Construct the `powers` array by iterating through the bits of `n`. If a bit is set (i.e., equal to 1), the corresponding power of 2 is added to the `powers` array. 2) Calculate the prefix products of the `powers` array. This allows us to efficiently compute the product of elements within a range. 3) For each query `[left, right]`, calculate the product of the elements from `powers[left]` to `powers[right]` using the prefix products and modular arithmetic. Specifically, the product is equal to `prefix_products[right + 1] / prefix_products[left]`, which is computed as `prefix_products[right + 1] * (prefix_products[left])^(MOD-2) mod MOD`.

Step-by-Step Algorithm

  1. Step 1: Create an empty array called `powers` to store the powers of 2.
  2. Step 2: Iterate through the bits of the integer `n` (from the least significant bit to the most significant bit). This can be done by checking `(n >> i) & 1` where `i` ranges from 0 to 30.
  3. Step 3: If the `i`-th bit is set, calculate 2^i and add it to the `powers` array.
  4. Step 4: Create a `prefix_products` array. The first element is 1. Then calculate each element by multiplying the previous element with the corresponding element in powers[i], modulo MOD. `prefix_products[i + 1] = (prefix_products[i] * powers[i]) % MOD`
  5. Step 5: Iterate through the queries array. For each query `[left, right]`, retrieve `prefix_products[right + 1]` and `prefix_products[left]`.
  6. Step 6: Calculate the modular inverse of `prefix_products[left]` using Fermat's Little Theorem: `pow(prefix_products[left], MOD - 2, MOD)`. Assign to `inv_denominator`.
  7. Step 7: Multiply `prefix_products[right + 1]` with `inv_denominator` modulo `MOD`: `(prefix_products[right + 1] * inv_denominator) % MOD`. Add the result to the `answers` array.
  8. Step 8: Return the `answers` array.

Key Insights

  • Insight 1: Representing a number as a sum of distinct powers of 2 is equivalent to finding the set bits in its binary representation. This directly gives us the `powers` array.
  • Insight 2: Calculating prefix products allows us to efficiently compute the product within a range by dividing the prefix product at the `right` index by the prefix product at the `left - 1` index. However, since we need to perform modulo arithmetic, division is replaced by multiplying with the modular inverse.
  • Insight 3: Utilizing modular exponentiation with Fermat's Little Theorem optimizes the computation of the modular inverse, as direct division is not possible under modulo.
  • Insight 4: In the Java/C/C++ implementation exponents themselves are used for calculating the total exponent, then a power function (fast exponentiation) is called to avoid overflow.

Complexity Analysis

Time Complexity: O(m + log n)

Space Complexity: O(log n)

Topics

This problem involves: Array, Bit Manipulation, Prefix Sum.

Companies

Asked at: Goldman Sachs, IBM.