Finding Maximum Length Subsequence with Product Conditions
Last Updated :
01 Feb, 2024
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);
Time Complexity: O(N * sqrt(X)), where X is the maximum element in input array A[].
Auxiliary space: O(N), As HashMap is used.
Similar Reads
Find the Increasing subsequence of length three with maximum product Given a sequence of non-negative integers, find the subsequence of length 3 having maximum product with the numbers of the subsequence being in ascending order. Examples: Input: arr[] = {6, 7, 8, 1, 2, 3, 9, 10} Output: 8 9 10 Input: arr[] = {1, 5, 10, 8, 9} Output: 5 8 9 Approach: Since we want to
10 min read
Count of K length subsequence whose product is even Given an array arr[] and an integer K, the task is to find number of non empty subsequence of length K from the given array arr of size N such that the product of subsequence is a even number.Example: Input: arr[] = [2, 3, 1, 7], K = 3 Output: 3 Explanation: There are 3 subsequences of length 3 whos
6 min read
Maximizing Product-Weighted Subsequence Length Given an array arr[] of size N, you have to find the length of the longest subsequence such that the product of the elements in the subsequence divided by the factorial of its length is maximized. Examples: Input: N = 5, arr[] = {1, 2, 4, 5, 2}Output: 2Explanation: We can choose 4 and 5 giving an an
5 min read
Maximum length Subsequence with Product less than given value for each query Given an array of positive integers arr[] of length N and a query array query[] of length M, the task is to find the maximum length subsequence in the array whose product is not greater than query [i] for all the queries. Input: arr[] = {4, 5, 2, 1} queries[] = {3, 10, 21}Output: {2, 3, 3}Explanatio
8 min read
Number of subsequences with negative product Given an array arr[] of N integers, the task is to find the count of all the subsequences of the array that have a negative products. Examples: Input: arr[] = {1, -5, -6} Output: 4 Explanation {-5}, {-6}, {1, -5} and {1, -6} are the only possible subsequences Input: arr[] = {2, 3, 1} Output: 0 Expla
6 min read