Open In App

Find pairs of elements from two different arrays whose product is a perfect square

Improve
Improve
Like Article
Like
Save
Share
Report

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 = 441

Input: 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);


Output: 

(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)



Last Updated : 08 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads