Open In App

Finding Maximum Length Subsequence with Product Conditions

Last Updated : 01 Feb, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

Given an array A[] of length N, find the length of the longest subsequence S such that:

  • If we took even number of elements from S, then the product of those elements should be a perfect square.
  • If we took odd number of elements from S, then the product of those elements should not be a perfect square.

If there is no possible subsequence then return 0.

Examples:

Input: N = 5, A[] = {27, 8, 12, 16, 12}
Output: 3
Explanation: Longest Subsequence S will be: {27, 12, 12}

  • Traversing from left to right on S, we can choose even-length such subsequences as: {27, 12} and {12, 12}. Which gives product of their elements as: 324 and 144 respectively. It can be verified that both are 324 and 144 are perfect squares of 18 and 12 respectively.
  • Traversing from left to right on S, we can choose odd-length such subsequences as: {27}, {12}, and {27, 12, 12}. Which gives product of their elements as: 27, 12 and 3888 respectively. It can be verified that none of them are perfect squares.

Thus, It is proved that S follows all the given conditions, and it is the longest subsequence of length 3.

Input: N = 2, A[] = {9, 1}
Output: 0
Explanation: It can be verified that no such subsequence S is possible there.

Approach: Implement the idea below to solve the problem

The problem is based on Number theory and can be solved using some observations.

  • Let the longest sub-sequence according to given conditions be S = {A1, A2, A3, . . . . ., Ak} of length K.
  • So, S will be a subsequence in which any odd-length sub-sequence shouldn’t be a perfect square => Which implies that Ai shouldn’t be a perfect square (No individual element can be a perfect square).
  • For an even-length subsequence of S, simple two elements say {Ai, Aj}. Then (Ai * Aj) should be a perfect square but none of them individually should be a perfect square. Hence, for all common prime factors of Ai and Aj each one of them should occur odd number of times in Ai and Aj, while all other uncommon prime factors should occur even number of times.
  • Extending the idea from the above points, in S for all elements Ai there should be a common prime factor with odd number of times in each Ai.
  • So, we store the number of odd occurrences of a prime or a composite number (as all elements can have more than 1 common prime factor with odd occurrences in each of them), and the maximum of all those would be the answer since each one of the odd occurrences represents a number in the input array.

Steps were taken to solve the problem:

  • Create a variable say res to store the ans.
  • Discard all the elements which are perfect square.
  • Declare a HashMap to store the frequency of product of factors, say freq.
  • For every element arr[i],
    • Prime factorize arr[i] to store the factors as key and the number of times the factor divides arr[i] as value.
    • Now, since we need the factors which divide arr[i] only odd number of times, discard all the other factors.
    • Find the product of the remaining factors, say prod.
    • Now, whenever we encounter any other element arr[j] which has the same product, then these two elements can together form a valid subsequence.
    • Increment the frequency of prod.
  • Finally, iterate over the freq map, and return the largest frequency as the answer.

Code to implement the approach:

C++14




// C++ code to implement the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to find the prime
// factorization of a number
unordered_map<int, int> getPrimeFactorisation(int num)
{
 
    // Map to store the factors with
    // their frequencies
    unordered_map<int, int> factors;
    for (int i = 2; i * i <= num; i++) {
        int cnt = 0;
        while (num % i == 0) {
            num /= i;
            cnt += 1;
        }
        factors[i] = cnt;
    }
    if (num > 1) {
        factors[num] = 1;
    }
    return factors;
}
 
// Checking if a number is a perfect
// square or not
bool isPerfectSquare(int x)
{
    int s = sqrt(x);
    return s * s == x;
}
 
// Driver Function
int main()
{
    // Inputs
    int N = 5;
    int A[] = { 27, 8, 12, 16, 12 };
 
    int res = 0;
 
    // New vector to store only those numbers
    // which are not perfect squares
    vector<int> arr;
 
    // Discard all the numbers which are
    // perfect squares
    for (int i = 0; i < N; i++) {
        if (!isPerfectSquare(A[i])) {
            arr.push_back(A[i]);
        }
    }
 
    // Hashmap to store the product of factors
    // which occur odd number of times
    unordered_map<int, int> freq;
    for (int i = 0; i < arr.size(); i++) {
        // key -> prime factor of arr[i]
        // value -> number of times we can
        // divide arr[i] with key
        unordered_map<int, int> factors
            = getPrimeFactorisation(arr[i]);
        int prod = 1;
 
        // Iterate over all the factors
        // and their frequencies
        for (auto factor : factors) {
            int key = factor.first;
            int value = factor.second;
 
            // Check if the factor occurs
            // odd number of times
            if (value % 2 != 0) {
                prod *= key;
            }
        }
 
        // Increment the frequency of prod by 1
        if (freq.find(prod) != freq.end()) {
            freq[prod]++;
        }
        else {
            freq[prod] = 1;
        }
    }
 
    for (auto f : freq) {
        res = max(res, f.second);
    }
 
    // Printing desired output
    cout << res << endl;
 
    return 0;
}


Java




// Java code to implement the approach
 
import java.util.*;
 
// Driver Class
class GFG {
    // Driver Function
    public static void main(String[] args)
    {
 
        // Inputs
        int N = 5;
        int[] A = { 27, 8, 12, 16, 12 };
 
        int res = 0;
 
        // New array to store only those numbers which are
        // not perfect squares
        ArrayList<Integer> arr = new ArrayList<Integer>();
 
        // Discard all the numbers which are perfect squares
        for (int i = 0; i < N; i++) {
            if (!isPerfectSquare(A[i]))
                arr.add(A[i]);
        }
 
        // Hashmap to store the product of factors which
        // occur odd number of times
        HashMap<Integer, Integer> freq = new HashMap<>();
        for (int i = 0; i < arr.size(); i++) {
            // key -> prime factor of arr[i]
            // value -> number of times we can divide arr[i]
            // with key
            HashMap<Integer, Integer> factors
                = getPrimeFactorisation(arr.get(i));
            int prod = 1;
 
            // Iterate over all the factors and their
            // frequencies
            for (Map.Entry<Integer, Integer> factor :
                 factors.entrySet()) {
                int key = factor.getKey();
                int value = factor.getValue();
                // Check if the factor occurs odd number of
                // times
                if (value % 2 != 0) {
                    prod *= key;
                }
            }
            // Increment the frequency of prod by 1
            if (freq.containsKey(prod)) {
                freq.put(prod, freq.get(prod) + 1);
            }
            else {
                freq.put(prod, 1);
            }
        }
 
        for (Map.Entry<Integer, Integer> f :
             freq.entrySet()) {
            res = Math.max(res, f.getValue());
        }
 
        // Printing desired output
        System.out.println(res);
    }
 
    // Method to find the prime factorization of a number
    static HashMap<Integer, Integer>
    getPrimeFactorisation(int num)
    {
        // Map to store the factors with their frequencies
        HashMap<Integer, Integer> factors = new HashMap<>();
        for (int i = 2; i * i <= num; i++) {
            int cnt = 0;
            while (num % i == 0) {
                num /= i;
                cnt += 1;
            }
            factors.put(i, cnt);
        }
        if (num > 1)
            factors.put(num, 1);
        return factors;
    }
 
    // Checking that X is a perfect square or not
    static boolean isPerfectSquare(int x)
    {
        int s = (int)Math.sqrt(x);
        return s * s == x;
    }
}


Python3




from math import sqrt
 
# Function to find the prime factorization of a number
def get_prime_factorization(num):
    factors = {}
    i = 2
    while i * i <= num:
        cnt = 0
        while num % i == 0:
            num //= i
            cnt += 1
        if cnt > 0:
            factors[i] = cnt
        i += 1
    if num > 1:
        factors[num] = 1
    return factors
 
# Checking if a number is a perfect square or not
def is_perfect_square(x):
    s = int(sqrt(x))
    return s * s == x
 
# Driver Function
if __name__ == "__main__":
    # Inputs
    N = 5
    A = [27, 8, 12, 16, 12]
 
    res = 0
 
    # New list to store only those numbers which are not perfect squares
    arr = []
 
    # Discard all the numbers which are perfect squares
    for num in A:
        if not is_perfect_square(num):
            arr.append(num)
 
    # Dictionary to store the product of factors which occur an odd number of times
    freq = {}
    for num in arr:
        # Get prime factorization of the number
        factors = get_prime_factorization(num)
        prod = 1
 
        # Iterate over all the factors and their frequencies
        for key, value in factors.items():
            # Check if the factor occurs odd number of times
            if value % 2 != 0:
                prod *= key
 
        # Increment the frequency of prod by 1
        freq[prod] = freq.get(prod, 0) + 1
 
    res = max(freq.values(), default=0)
 
    # Printing desired output
    print(res)
 
# This code is contributed by shivamgupta0987654321


C#




using System;
using System.Collections.Generic;
 
class Program {
    // Function to find the prime
    // factorization of a number
    static Dictionary<int, int>
    GetPrimeFactorization(int num)
    {
        // Dictionary to store the factors with their
        // frequencies
        Dictionary<int, int> factors
            = new Dictionary<int, int>();
 
        for (int i = 2; i * i <= num; i++) {
            int cnt = 0;
            while (num % i == 0) {
                num /= i;
                cnt += 1;
            }
            factors[i] = cnt;
        }
 
        if (num > 1) {
            factors[num] = 1;
        }
 
        return factors;
    }
 
    // Checking if a number is a perfect square or not
    static bool IsPerfectSquare(int x)
    {
        int s = (int)Math.Sqrt(x);
        return s * s == x;
    }
 
    // Driver Function
    static void Main()
    {
        // Inputs
        int N = 5;
        int[] A = { 27, 8, 12, 16, 12 };
 
        int res = 0;
 
        // New list to store only those numbers which are
        // not perfect squares
        List<int> arr = new List<int>();
 
        // Discard all the numbers which are perfect squares
        for (int i = 0; i < N; i++) {
            if (!IsPerfectSquare(A[i])) {
                arr.Add(A[i]);
            }
        }
 
        // Dictionary to store the product of factors which
        // occur odd number of times
        Dictionary<int, int> freq
            = new Dictionary<int, int>();
 
        for (int i = 0; i < arr.Count; i++) {
            // key -> prime factor of arr[i]
            // value -> number of times we can divide arr[i]
            // with key
            Dictionary<int, int> factors
                = GetPrimeFactorization(arr[i]);
            int prod = 1;
 
            // Iterate over all the factors and their
            // frequencies
            foreach(var factor in factors)
            {
                int key = factor.Key;
                int value = factor.Value;
 
                // Check if the factor occurs odd number of
                // times
                if (value % 2 != 0) {
                    prod *= key;
                }
            }
 
            // Increment the frequency of prod by 1
            if (freq.ContainsKey(prod)) {
                freq[prod]++;
            }
            else {
                freq[prod] = 1;
            }
        }
 
        foreach(var f in freq)
        {
            res = Math.Max(res, f.Value);
        }
 
        // Printing desired output
        Console.WriteLine(res);
    }
}


Javascript




//Javascript Code
 
// Function to find the prime factorization of a number
function getPrimeFactorization(num) {
    const factors = {};
    let i = 2;
    while (i * i <= num) {
        let cnt = 0;
        while (num % i === 0) {
            num /= i;
            cnt += 1;
        }
        if (cnt > 0) {
            factors[i] = cnt;
        }
        i += 1;
    }
    if (num > 1) {
        factors[num] = 1;
    }
    return factors;
}
 
// Checking if a number is a perfect square or not
function isPerfectSquare(x) {
    const s = parseInt(Math.sqrt(x));
    return s * s === x;
}
 
// Inputs
const N = 5;
const A = [27, 8, 12, 16, 12];
 
let res = 0;
 
// New array to store only those numbers which are not perfect squares
const arr = [];
 
// Discard all the numbers which are perfect squares
for (const num of A) {
    if (!isPerfectSquare(num)) {
        arr.push(num);
    }
}
 
// Map to store the product of factors which occur an odd number of times
const freq = {};
for (const num of arr) {
    // Get prime factorization of the number
    const factors = getPrimeFactorization(num);
    let prod = 1;
 
    // Iterate over all the factors and their frequencies
    for (const [key, value] of Object.entries(factors)) {
        // Check if the factor occurs odd number of times
        if (value % 2 !== 0) {
            prod *= parseInt(key);
        }
    }
 
    // Increment the frequency of prod by 1
    freq[prod] = (freq[prod] || 0) + 1;
}
 
res = Math.max(...Object.values(freq), 0);
 
// Printing desired output
console.log(res);


Output

3

Time Complexity: O(N * sqrt(X)), where X is the maximum element in input array A[].
Auxiliary space: O(N), As HashMap is used.



Like Article
Suggest improvement
Share your thoughts in the comments

Similar Reads