C++ Program for Products of ranges in an array
Given an array A[] of size N. Solve Q queries. Find the product in the range [L, R] under modulo P ( P is Prime).
Examples:
Input : A[] = {1, 2, 3, 4, 5, 6} L = 2, R = 5, P = 229 Output : 120 Input : A[] = {1, 2, 3, 4, 5, 6}, L = 2, R = 5, P = 113 Output : 7
Brute Force
For each of the queries, traverse each element in the range [L, R] and calculate the product under modulo P. This will answer each query in O(N).
C++
// Product in range // Queries in O(N) #include <bits/stdc++.h> using namespace std; // Function to calculate // Product in the given range. int calculateProduct( int A[], int L, int R, int P) { // As our array is 0 based // as and L and R are given // as 1 based index. L = L - 1; R = R - 1; int ans = 1; for ( int i = L; i <= R; i++) { ans = ans * A[i]; ans = ans % P; } return ans; } // Driver code int main() { int A[] = { 1, 2, 3, 4, 5, 6 }; int P = 229; int L = 2, R = 5; cout << calculateProduct(A, L, R, P) << endl; L = 1, R = 3; cout << calculateProduct(A, L, R, P) << endl; return 0; } |
Output :
120 6
Efficient Using Modular Multiplicative Inverse:
As P is prime, we can use Modular Multiplicative Inverse. Using dynamic programming, we can calculate a pre-product array under modulo P such that the value at index i contains the product in the range [0, i]. Similarly, we can calculate the pre-inverse product under modulo P. Now each query can be answered in O(1).
The inverse product array contains the inverse product in the range [0, i] at index i. So, for the query [L, R], the answer will be Product[R]*InverseProduct[L-1]
Note: We can not calculate the answer as Product[R]/Product[L-1] because the product is calculated under modulo P. If we do not calculate the product under modulo P there is always a possibility of overflow.
C++
// Product in range Queries in O(1) #include <bits/stdc++.h> using namespace std; #define MAX 100 int pre_product[MAX]; int inverse_product[MAX]; // Returns modulo inverse of a // with respect to m using // extended Euclid Algorithm // Assumption: a and m are // coprimes, i.e., gcd(a, m) = 1 int modInverse( int a, int m) { int m0 = m, t, q; int x0 = 0, x1 = 1; if (m == 1) return 0; while (a > 1) { // q is quotient q = a / m; t = m; // m is remainder now, // process same as // Euclid's algo m = a % m, a = t; t = x0; x0 = x1 - q * x0; x1 = t; } // Make x1 positive if (x1 < 0) x1 += m0; return x1; } // calculating pre_product // array void calculate_Pre_Product( int A[], int N, int P) { pre_product[0] = A[0]; for ( int i = 1; i < N; i++) { pre_product[i] = pre_product[i - 1] * A[i]; pre_product[i] = pre_product[i] % P; } } // Calculating inverse_product // array. void calculate_inverse_product( int A[], int N, int P) { inverse_product[0] = modInverse(pre_product[0], P); for ( int i = 1; i < N; i++) inverse_product[i] = modInverse(pre_product[i], P); } // Function to calculate // Product in the given range. int calculateProduct( int A[], int L, int R, int P) { // As our array is 0 based as // and L and R are given as 1 // based index. L = L - 1; R = R - 1; int ans; if (L == 0) ans = pre_product[R]; else ans = pre_product[R] * inverse_product[L - 1]; return ans; } // Driver Code int main() { // Array int A[] = { 1, 2, 3, 4, 5, 6 }; int N = sizeof (A) / sizeof (A[0]); // Prime P int P = 113; // Calculating PreProduct // and InverseProduct calculate_Pre_Product(A, N, P); calculate_inverse_product(A, N, P); // Range [L, R] in 1 base index int L = 2, R = 5; cout << calculateProduct(A, L, R, P) << endl; L = 1, R = 3; cout << calculateProduct(A, L, R, P) << endl; return 0; } |
Output :
7 6
Please refer complete article on Products of ranges in an array for more details!
Please Login to comment...