Queries to calculate GCD of an array after multiplying first or last K elements by X
Given an array arr[] consisting of N positive integers and a 2D array queries[][] of the type {a, K, X} such that if the value of a is 1, then multiply first K array elements by X. Otherwise, multiply last K array elements by X. The task is to calculate GCD of the array after performing each query on the original array.
Examples:
Input: arr[] = {2, 3, 4, 8}, Queries[][3] = {{1, 2, 2}, {2, 4, 5}}
Output: 2 5
Explanation:
Query 1: The given query is {1, 2, 2}. After multiplying the first 2 array elements by 2, arr[] modifies to {4, 6, 4, 8}. GCD of the modified array is 2.
Query 2: The given query is {2, 4, 5}. After multiplying the last 4 elements array elements by 5, arr[] modifies to {10, 15, 20, 40}. GCD of the updated array is 5.Input: arr[] = {4, 12, 4, 9}, Queries[][3] = {{1, 3, 3}, {2, 4, 1}}
Output: 3 1
Naive Approach: The simplest approach is to update the given array by performing each query and then find the GCD of the updated array.
Time Complexity: O(N * Q * log(M)), where M is the maximum element present in the array.
Auxiliary Space: O(N)
Efficient Approach: The above approach can be optimized by storing the prefix and suffix GCD arrays of the given array and solving each query in O(1) time by following the below steps:
- Initialize an array prefix[] and suffix[] of size N to store the prefix and suffix GCD arrays of the given array.
- Traverse the array from the front and the back and find the prefix and suffix GCD at each index and store it in prefix[] and suffix[] respectively.
- Now, traverse the array queries[] and for each query {a, K, X} perform the following:
- If the value of K is N then print the value of prefix[N – 1] * X as the result.
- If the value of a is 1, then find the GCD of prefix[K – 1] * X and suffix[K] as the result as the prefix[K – 1] * X is the new GCD of first K numbers and suffix[K + 1] is the GCD of the remaining array elements.
- If the value of a is 2, then find the GCD of prefix[N – K – 1] and suffix[N – K] * X as the result as the prefix[N – K – 1] * X is the new GCD of first K numbers and suffix[N – K] is the GCD of the remaining array elements.
Below is the implementation of the above approach:
C++
// C++ program for the above approach #include <bits/stdc++.h> using namespace std; // Function to find the GCD after performing // each query on array elements void findGCDQueries( int arr[], int N, int Queries[][3], int Q) { // Stores prefix array and suffix // array int prefix[N], suffix[N]; prefix[0] = arr[0]; suffix[N - 1] = arr[N - 1]; // Build prefix array for ( int i = 1; i < N; i++) { prefix[i] = __gcd(prefix[i - 1], arr[i]); } // Build suffix array for ( int i = N - 2; i >= 0; i--) { suffix[i] = __gcd(suffix[i + 1], arr[i]); } // Traverse queries array for ( int i = 0; i < Q; i++) { int a = Queries[i][0]; int K = Queries[i][1]; int X = Queries[i][2]; // Edge Case when update is // is required till the end if (K == N) { cout << prefix[N - 1] * X; continue ; } // Edge Case when update is // is required till the front if (a == 1) { cout << __gcd(prefix[K - 1] * X, suffix[K]); } // Find the resultant operation // for each query else { cout << __gcd(suffix[N - K] * X, prefix[N - K - 1]); } cout << " " ; } } // Driver Code int main() { int arr[] = { 2, 3, 4, 8 }; int N = sizeof (arr) / sizeof (arr[0]); int Queries[][3] = { { 1, 2, 2 }, { 2, 4, 5 } }; int Q = sizeof (Queries) / sizeof (Queries[0]); findGCDQueries(arr, N, Queries, Q); return 0; } |
Java
// Java program to implement // the above approach import java.io.*; import java.util.*; class GFG { // Recursive function to return gcd of a and b static int gcd( int a, int b) { // Everything divides 0 if (a == 0 ) return b; if (b == 0 ) return a; // base case if (a == b) return a; // a is greater if (a > b) return gcd(a - b, b); return gcd(a, b - a); } // Function to find the GCD after performing // each query on array elements static void findGCDQueries( int arr[], int N, int Queries[][], int Q) { // Stores prefix array and suffix // array int prefix[] = new int [N], suffix[] = new int [N]; prefix[ 0 ] = arr[ 0 ]; suffix[N - 1 ] = arr[N - 1 ]; // Build prefix array for ( int i = 1 ; i < N; i++) { prefix[i] = gcd(prefix[i - 1 ], arr[i]); } // Build suffix array for ( int i = N - 2 ; i >= 0 ; i--) { suffix[i] = gcd(suffix[i + 1 ], arr[i]); } // Traverse queries array for ( int i = 0 ; i < Q; i++) { int a = Queries[i][ 0 ]; int K = Queries[i][ 1 ]; int X = Queries[i][ 2 ]; // Edge Case when update is // is required till the end if (K == N) { System.out.print(prefix[N - 1 ] * X); continue ; } // Edge Case when update is // is required till the front if (a == 1 ) { System.out.print(gcd(prefix[K - 1 ] * X, suffix[K])); } // Find the resultant operation // for each query else { System.out.print(gcd(suffix[N - K] * X, prefix[N - K - 1 ])); } System.out.print( " " ); } } // Driver Code public static void main(String[] args) { int arr[] = { 2 , 3 , 4 , 8 }; int N = arr.length; int Queries[][] = { { 1 , 2 , 2 }, { 2 , 4 , 5 } }; int Q = Queries.length; findGCDQueries(arr, N, Queries, Q); } } // This code is contributed by sanjoy_62. |
Python3
# Python 3 program for the above approach from math import gcd # Function to find the GCD after performing # each query on array elements def findGCDQueries(arr, N, Queries, Q): # Stores prefix array and suffix # array prefix = [ 0 for i in range (N)] suffix = [ 0 for i in range (N)] prefix[ 0 ] = arr[ 0 ] suffix[N - 1 ] = arr[N - 1 ] # Build prefix array for i in range ( 1 ,N, 1 ): prefix[i] = gcd(prefix[i - 1 ], arr[i]) # Build suffix array i = N - 2 while (i> = 0 ): suffix[i] = gcd(suffix[i + 1 ], arr[i]) i - = 1 # Traverse queries array for i in range (Q): a = Queries[i][ 0 ] K = Queries[i][ 1 ] X = Queries[i][ 2 ] # Edge Case when update is # is required till the end if (K = = N): print (prefix[N - 1 ] * X,end = " " ) continue # Edge Case when update is # is required till the front if (a = = 1 ): print (gcd(prefix[K - 1 ] * X,suffix[K]),end = " " ) # Find the resultant operation # for each query else : print (gcd(suffix[N - K] * X, prefix[N - K - 1 ]),end = " " ) # Driver Code if __name__ = = '__main__' : arr = [ 2 , 3 , 4 , 8 ] N = len (arr) Queries = [[ 1 , 2 , 2 ], [ 2 , 4 , 5 ]] Q = len (Queries) findGCDQueries(arr, N, Queries, Q) # This code is contributed by SURENDRA_GANGWAR. |
C#
// C# program to implement // the above approach using System; public class GFG { // Recursive function to return gcd of a and b static int gcd( int a, int b) { // Everything divides 0 if (a == 0) return b; if (b == 0) return a; // base case if (a == b) return a; // a is greater if (a > b) return gcd(a - b, b); return gcd(a, b - a); } // Function to find the GCD after performing // each query on array elements static void findGCDQueries( int []arr, int N, int [,]Queries, int Q) { // Stores prefix array and suffix // array int []prefix = new int [N]; int []suffix = new int [N]; prefix[0] = arr[0]; suffix[N - 1] = arr[N - 1]; // Build prefix array for ( int i = 1; i < N; i++) { prefix[i] = gcd(prefix[i - 1], arr[i]); } // Build suffix array for ( int i = N - 2; i >= 0; i--) { suffix[i] = gcd(suffix[i + 1], arr[i]); } // Traverse queries array for ( int i = 0; i < Q; i++) { int a = Queries[i,0]; int K = Queries[i,1]; int X = Queries[i,2]; // Edge Case when update is // is required till the end if (K == N) { Console.Write(prefix[N - 1] * X); continue ; } // Edge Case when update is // is required till the front if (a == 1) { Console.Write(gcd(prefix[K - 1] * X, suffix[K])); } // Find the resultant operation // for each query else { Console.Write(gcd(suffix[N - K] * X, prefix[N - K - 1])); } Console.Write( " " ); } } // Driver Code public static void Main( string [] args) { int []arr = { 2, 3, 4, 8 }; int N = arr.Length; int [,]Queries = { { 1, 2, 2 }, { 2, 4, 5 } }; int Q = Queries.GetLength(0); findGCDQueries(arr, N, Queries, Q); } } // This code is contributed by AnkThon. |
Javascript
<script> // JavaScript program to implement the above approach // Recursive function to return gcd of a and b function gcd(a, b) { // Everything divides 0 if (a == 0) return b; if (b == 0) return a; // base case if (a == b) return a; // a is greater if (a > b) return gcd(a - b, b); return gcd(a, b - a); } // Function to find the GCD after performing // each query on array elements function findGCDQueries(arr, N, Queries, Q) { // Stores prefix array and suffix // array let prefix = new Array(N), suffix = new Array(N); prefix[0] = arr[0]; suffix[N - 1] = arr[N - 1]; // Build prefix array for (let i = 1; i < N; i++) { prefix[i] = gcd(prefix[i - 1], arr[i]); } // Build suffix array for (let i = N - 2; i >= 0; i--) { suffix[i] = gcd(suffix[i + 1], arr[i]); } // Traverse queries array for (let i = 0; i < Q; i++) { let a = Queries[i][0]; let K = Queries[i][1]; let X = Queries[i][2]; // Edge Case when update is // is required till the end if (K == N) { document.write(prefix[N - 1] * X); continue ; } // Edge Case when update is // is required till the front if (a == 1) { document.write(gcd(prefix[K - 1] * X, suffix[K])); } // Find the resultant operation // for each query else { document.write(gcd(suffix[N - K] * X, prefix[N - K - 1])); } document.write( " " ); } } let arr = [ 2, 3, 4, 8 ]; let N = arr.length; let Queries = [ [ 1, 2, 2 ], [ 2, 4, 5 ] ]; let Q = Queries.length; findGCDQueries(arr, N, Queries, Q); </script> |
2 5
Time Complexity: O((N + Q)* log M), where M is the maximum element of the array.
Auxiliary Space: O(N)
Please Login to comment...