Find pairs of elements from two different arrays whose product is a perfect square
Prerequisites: Prime Factorization using Sieve
Given two arrays arr1[] and arr2[] of size M and N with distinct elements in each of the arrays, the task is to find those pair of elements (one from the first array and other from the second array) whose product is a perfect square. Print -1 if no pairs can be formed.
Examples:
Input: arr1[] = {1, 8, 6, 9}, arr2[] = {2, 24, 49}
Output: (1, 49), (8, 2), (6, 24), (9, 49)
Explanation:
The product of pairs in the output are all perfect squares.
Pair 1: 1 x 49 = 49
Pair 2: 8 x 2 = 16
Pair 3: 6 x 24 = 144
Pair 4: 9 x 49 = 441Input: arr1[] = {2, 3, 4}, arr2[] = {9, 5}
Output: -1
Naive Approach: Naive approach is to choose all the possible pairs and check if they form a perfect square. This can be done in quadratic time.
Time Complexity: O(M*N)
Auxiliary space: O(1)
Efficient Approach: The idea is to use the concept of prime factorization. Let’s analyse how to use the concept in this problem.
The following are the scenarios where the product of two numbers form a perfect square:
- If both the numbers are perfect squares their product always form a perfect square.
- If one of the numbers is not a perfect square their product can never be a perfect square.
- In case both the numbers are non-perfect squares, then the number of prime factors of both the numbers combined have to be even.
- For example,
let x = 6, y = 1176
prime factorization of x = 2 x 3 (2 and 3 occurs odd times)
prime factorization of y = 2 x 2 x 2 x 3 x 7 x 7 (2 and 3 occurs odd times)
x * y = 7056 which is square of 84
- Since x and y have all odd times occurring primes, but x * y has even number of prime factors. Therefore, they will form a perfect square.
Therefore, the array arr1[] is traversed and for each element in arr1[], the numbers in array arr2[] which have same product of odd times occurring primes as of current element. This can be done using map STL in C++ in logn time.
Below is the implementation of the above approach:
C++
// C++ program to print pairs whose // product is a perfect square #include <bits/stdc++.h> using namespace std; // Maximum number upto which sieve is performed #define MAXN 100001 // Array to perform Sieve of Eratosthenes // and store prime numbers int spf[MAXN]; // Function to perform sieve of // eratosthenes on the array spf. void sieve() { spf[1] = 1; for ( int i = 2; i < MAXN; i++) spf[i] = i; for ( int i = 4; i < MAXN; i += 2) spf[i] = 2; for ( int i = 3; i * i < MAXN; i++) { if (spf[i] == i) { for ( int j = i * i; j < MAXN; j += i) if (spf[j] == j) spf[j] = i; } } } // Function to return the product of the // odd occurring prime factors of a number int getProductOddOccuringPrimes( int x) { // Product of 1 with perfect square gives // perfect square, 1 is returned for x = 1 if (x == 1) return 1; // Temporary container of prime factors vector< int > ret; while (x != 1) { ret.push_back(spf[x]); x = x / spf[x]; } // ans contains the product of primes // which occurs odd number of times int count = 1, ans = 1; for ( int i = 0, j = 1; j < ret.size(); ++j, ++i) { if (ret[i] != ret[j]) { if (count & 1) ans *= ret[i]; count = 0; } count++; } // Checks if count is odd or not if (count & 1) ans *= ret[ret.size() - 1]; return ans; } // Function to print the pairs whose product is // a perfect square void printPairs( int n, int m, int a[], int b[]) { int countPairs = 0; // For storing the indices with same // product of odd times occurring Primes as key map< int , vector< int > > productOfPrimes; // Every number from both the array is iterated // getProductOddOccuringPrimes function is called // and the product of odd occurring primes is // stored in the map productOfPrimes. // A pair is printed if the product is same for ( int i = 0; i < n; ++i) { // Generating the product of odd times // occurring primes int productPrimesOfA = getProductOddOccuringPrimes(a[i]); // Pushing the indices to the // vector with the product of // odd times occurring Primes productOfPrimes[productPrimesOfA].push_back(i); } for ( int i = 0; i < m; ++i) { // Generating the product of odd times // occurring Primes int productPrimesOfB = getProductOddOccuringPrimes(b[i]); // Checking if productPrimesOfB // lies in the productOfPrimes if (productOfPrimes.find(productPrimesOfB) != productOfPrimes.end()) { for ( auto itr : productOfPrimes[productPrimesOfB]) { countPairs++; cout << " (" << b[i] << ", " << a[itr] << ") " ; } } } if (countPairs <= 0) cout << "No pairs Found!" ; cout << endl; } // Driver function int main() { sieve(); // N, M are size of array a and b respectively int N = 5, M = 5; int a[] = { 4, 1, 6, 35, 120 }; int b[] = { 24, 140, 4, 30, 1 }; // Function that prints the pairs // whose product is a perfect square printPairs(N, M, a, b); return 0; } |
Java
// Java program to print pairs whose // product is a perfect square import java.util.*; class GFG{ // Maximum number upto which sieve is performed static final int MAXN = 100001 ; // Array to perform Sieve of Eratosthenes // and store prime numbers static int []spf = new int [MAXN]; // Function to perform sieve of // eratosthenes on the array spf. static void sieve() { spf[ 1 ] = 1 ; for ( int i = 2 ; i < MAXN; i++) spf[i] = i; for ( int i = 4 ; i < MAXN; i += 2 ) spf[i] = 2 ; for ( int i = 3 ; i * i < MAXN; i++) { if (spf[i] == i) { for ( int j = i * i; j < MAXN; j += i) if (spf[j] == j) spf[j] = i; } } } // Function to return the product of the // odd occurring prime factors of a number static int getProductOddOccuringPrimes( int x) { // Product of 1 with perfect square gives // perfect square, 1 is returned for x = 1 if (x == 1 ) return 1 ; // Temporary container of prime factors Vector<Integer> ret = new Vector<Integer>(); while (x != 1 ) { ret.add(spf[x]); x = x / spf[x]; } // ans contains the product of primes // which occurs odd number of times int count = 1 , ans = 1 ; for ( int i = 0 , j = 1 ; j < ret.size(); ++j, ++i) { if (ret.get(i) != ret.get(j)) { if (count % 2 == 1 ) ans *= ret.get(i); count = 0 ; } count++; } // Checks if count is odd or not if (count % 2 == 1 ) ans *= ret.get(ret.size() - 1 ); return ans; } // Function to print the pairs whose product is // a perfect square static void printPairs( int n, int m, int a[], int b[]) { int countPairs = 0 ; // For storing the indices with same // product of odd times occurring Primes as key Map<Integer, Vector<Integer>> productOfPrimes = new HashMap<Integer, Vector<Integer>>(); // Every number from both the array is iterated // getProductOddOccuringPrimes function is called // and the product of odd occurring primes is // stored in the map productOfPrimes. // A pair is printed if the product is same for ( int i = 0 ; i < n; ++i) { // Generating the product of odd times // occurring primes int productPrimesOfA = getProductOddOccuringPrimes(a[i]); // Pushing the indices to the // vector with the product of // odd times occurring Primes Vector<Integer> temp = new Vector<Integer>(); if (productOfPrimes.containsKey(productPrimesOfA)) for (Integer s:productOfPrimes.get(productPrimesOfA)){ temp.add(s); } temp.add(i); productOfPrimes.put(productPrimesOfA, temp); } for ( int i = 0 ; i < m; ++i) { // Generating the product of odd times // occurring Primes int productPrimesOfB = getProductOddOccuringPrimes(b[i]); // Checking if productPrimesOfB // lies in the productOfPrimes if (productOfPrimes.containsKey(productPrimesOfB)) { for (Integer itr : productOfPrimes.get(productPrimesOfB)) { countPairs++; System.out.print( " (" + b[i]+ ", " + a[itr]+ ") " ); } } } if (countPairs <= 0 ) System.out.print( "No pairs Found!" ); System.out.println(); } // Driver function public static void main(String[] args) { sieve(); // N, M are size of array a and b respectively int N = 5 , M = 5 ; int a[] = { 4 , 1 , 6 , 35 , 120 }; int b[] = { 24 , 140 , 4 , 30 , 1 }; // Function that prints the pairs // whose product is a perfect square printPairs(N, M, a, b); } } // This code is contributed by 29AjayKumar |
Python3
# Python program to print pairs whose # product is a perfect square import math # Maximum number upto which sieve is performed MAXN = 100001 # Array to perform Sieve of Eratosthenes # and store prime numbers spf = [ 0 ] * MAXN # Function to perform sieve of # eratosthenes on the array spf. def sieve(): spf[ 1 ] = 1 for i in range ( 2 , MAXN): spf[i] = i for i in range ( 4 , MAXN, 2 ): spf[i] = 2 for i in range ( 3 , int (math.sqrt(MAXN)) + 1 ): if spf[i] = = i: for j in range (i * i, MAXN, i): if spf[j] = = j: spf[j] = i # Function to return the product of the # odd occurring prime factors of a number def getProductOddOccuringPrimes(x): # Product of 1 with perfect square gives # perfect square, 1 is returned for x = 1 if x = = 1 : return 1 # Temporary container of prime factors ret = [] while x ! = 1 : ret.append(spf[x]) x = x / / spf[x] # ans contains the product of primes # which occurs odd number of times count, ans = 1 , 1 for i in range ( len (ret) - 1 ): if ret[i] ! = ret[i + 1 ]: if count % 2 ! = 0 : ans * = ret[i] count = 0 count + = 1 # Checks if count is odd or not if count % 2 ! = 0 : ans * = ret[ - 1 ] return ans # Function to print the pairs whose product is # a perfect square def printPairs(n, m, a, b): countPairs = 0 # For storing the indices with same # product of odd times occurring Primes as key productOfPrimes = {} # Every number from both the array is iterated # getProductOddOccuringPrimes function is called # and the product of odd occurring primes is # stored in the map productOfPrimes. # A pair is printed if the product is same for i in range (n): # Generating the product of odd times # occurring primes productPrimesOfA = getProductOddOccuringPrimes(a[i]) # Pushing the indices to the # vector with the product of # odd times occurring Primes if productPrimesOfA in productOfPrimes: productOfPrimes[productPrimesOfA].append(i) else : productOfPrimes[productPrimesOfA] = [i] for i in range (m): # Generating the product of odd times # occurring Primes productPrimesOfB = getProductOddOccuringPrimes(b[i]) # Checking if productPrimesOfB # lies in the productOfPrimes if productPrimesOfB in productOfPrimes: for j in productOfPrimes[productPrimesOfB]: countPairs + = 1 print ( "(" ,b[i], "," , a[j], ")" ,end = " " ) if countPairs < = 0 : print ( "No pairs Found!" ) print () # Driver function sieve() # N, M are size of array a and b respectively N,M = 5 , 5 a = [ 4 , 1 , 6 , 35 , 120 ] b = [ 24 , 140 , 4 , 30 , 1 ] # Function that prints the pairs # whose product is a perfect square printPairs(N, M, a, b) # This code is contributed by Utkarsh Kumar. |
C#
// C# program to print pairs whose // product is a perfect square using System; using System.Collections.Generic; class GFG{ // Maximum number upto which sieve is performed static readonly int MAXN = 100001; // Array to perform Sieve of Eratosthenes // and store prime numbers static int []spf = new int [MAXN]; // Function to perform sieve of // eratosthenes on the array spf. static void sieve() { spf[1] = 1; for ( int i = 2; i < MAXN; i++) spf[i] = i; for ( int i = 4; i < MAXN; i += 2) spf[i] = 2; for ( int i = 3; i * i < MAXN; i++) { if (spf[i] == i) { for ( int j = i * i; j < MAXN; j += i) if (spf[j] == j) spf[j] = i; } } } // Function to return the product of the // odd occurring prime factors of a number static int getProductOddOccuringPrimes( int x) { // Product of 1 with perfect square gives // perfect square, 1 is returned for x = 1 if (x == 1) return 1; // Temporary container of prime factors List< int > ret = new List< int >(); while (x != 1) { ret.Add(spf[x]); x = x / spf[x]; } // ans contains the product of primes // which occurs odd number of times int count = 1, ans = 1; for ( int i = 0, j = 1; j < ret.Count; ++j, ++i) { if (ret[i] != ret[j]) { if (count % 2 == 1) ans *= ret[i]; count = 0; } count++; } // Checks if count is odd or not if (count %2 == 1) ans *= ret[ret.Count - 1]; return ans; } // Function to print the pairs whose product is // a perfect square static void printPairs( int n, int m, int []a, int []b) { int countPairs = 0; // For storing the indices with same // product of odd times occurring Primes as key Dictionary< int , List< int >> productOfPrimes = new Dictionary< int , List< int >>(); // Every number from both the array is iterated // getProductOddOccuringPrimes function is called // and the product of odd occurring primes is // stored in the map productOfPrimes. // A pair is printed if the product is same for ( int i = 0; i < n; ++i) { // Generating the product of odd times // occurring primes int productPrimesOfA = getProductOddOccuringPrimes(a[i]); // Pushing the indices to the // vector with the product of // odd times occurring Primes List< int > temp = new List< int >(); if (productOfPrimes.ContainsKey(productPrimesOfA)) foreach ( int s in productOfPrimes[productPrimesOfA]){ temp.Add(s); } temp.Add(i); if (productOfPrimes.ContainsKey(productPrimesOfA)) productOfPrimes[productPrimesOfA] = temp; else productOfPrimes.Add(productPrimesOfA, temp); } for ( int i = 0; i < m; ++i) { // Generating the product of odd times // occurring Primes int productPrimesOfB = getProductOddOccuringPrimes(b[i]); // Checking if productPrimesOfB // lies in the productOfPrimes if (productOfPrimes.ContainsKey(productPrimesOfB)) { foreach ( int itr in productOfPrimes[productPrimesOfB]) { countPairs++; Console.Write( " (" + b[i]+ ", " + a[itr]+ ") " ); } } } if (countPairs <= 0) Console.Write( "No pairs Found!" ); Console.WriteLine(); } // Driver function public static void Main(String[] args) { sieve(); // N, M are size of array a and b respectively int N = 5, M = 5; int []a = { 4, 1, 6, 35, 120 }; int []b = { 24, 140, 4, 30, 1 }; // Function that prints the pairs // whose product is a perfect square printPairs(N, M, a, b); } } // This code is contributed by 29AjayKumar |
Javascript
// Maximum number upto which sieve is performed const MAXN = 100001; // Array to perform Sieve of Eratosthenes // and store prime numbers let spf = new Array(MAXN).fill(0); // Function to perform sieve of // eratosthenes on the array spf. function sieve(){ spf[1] = 1; for (let i = 2; i < MAXN; i++) { spf[i] = i; } for (let i = 4; i < MAXN; i += 2) { spf[i] = 2; } for (let i = 3; i < Math.sqrt(MAXN)+1; i++) { if (spf[i] == i) { for (let j = i * i; j < MAXN; j += i) { if (spf[j] == j) { spf[j] = i; } } } } } // Function to return the product of the // odd occurring prime factors of a number function getProductOddOccuringPrimes(x) { // Product of 1 with perfect square gives // perfect square, 1 is returned for x = 1 if (x == 1) { return 1; } // Temporary container of prime factors let ret = []; while (x != 1) { ret.push(spf[x]); x = Math.floor(x / spf[x]); } // ans contains the product of primes // which occurs odd number of times let count = 1; let ans = 1; for (let i = 0; i < ret.length - 1; i++) { if (ret[i] != ret[i+1]) { if (count % 2 != 0) { ans *= ret[i]; } count = 0; } count += 1; } // Checks if count is odd or not if (count % 2 != 0) { ans *= ret[ret.length - 1]; } return ans; } // Function to print the pairs whose product is // a perfect square function printPairs(n, m, a, b) { let countPairs = 0; // For storing the indices with same // product of odd times occurring Primes as key let productOfPrimes = {}; // Every number from both the array is iterated // getProductOddOccuringPrimes function is called // and the product of odd occurring primes is // stored in the map productOfPrimes. // A pair is printed if the product is same for (let i = 0; i < n; i++) { // Generating the product of odd times // occurring primes let productPrimesOfA = getProductOddOccuringPrimes(a[i]); // Pushing the indices to the // vector with the product of // odd times occurring Primes if (productPrimesOfA in productOfPrimes) { productOfPrimes[productPrimesOfA].push(i); } else { productOfPrimes[productPrimesOfA] = [i]; } } for (let i = 0; i < m; i++) { // Generating the product of odd times // occurring Primes let productPrimesOfB = getProductOddOccuringPrimes(b[i]); // Checking if productPrimesOfB // lies in the productOfPrimes if (productPrimesOfB in productOfPrimes) { for (let j of productOfPrimes[productPrimesOfB]) { countPairs += 1; console.log(`(${b[i]}, ${a[j]}) `); } } } if (countPairs <= 0) { console.log( "No pairs Found!" ); } console.log(); } // Driver function sieve(); // N, M are size of array a and b respectively let N = 5, M = 5; let a = [4, 1, 6, 35, 120]; let b = [24, 140, 4, 30, 1]; // Function that prints the pairs // whose product is a perfect square printPairs(N, M, a, b); |
(24, 6) (140, 35) (4, 4) (4, 1) (30, 120) (1, 4) (1, 1)
Time Complexity: O(Klog(K)) where K = max(N,M)
Auxiliary space: O(N+M+MAXN)
Contact Us