Given a sorted array of N integers. The task is to find the longest subsequence such that every element in the subsequence is reachable by multiplying any prime number to the previous element in the subsequence.
Note: A[i] <= 105
Examples:
Input: a[] = {3, 5, 6, 12, 15, 36}
Output 4
The longest subsequence is {3, 6, 12, 36}
6 = 3*2
12 = 6*2
36 = 12*32 and 3 are primes
Input: a[] = {1, 2, 5, 6, 12, 35, 60, 385}
Output: 5
Approach: The problem can be solved using pre-storing primes till the largest number in the array and using basic Dynamic Programming. The following steps can be followed to solve the above problem:
- Initially store all the primes in any of the Data-structure.
- Hash the index of the numbers in a hash-map.
- Create a dp[] of size N, and initialize it with 1 at every place, as the longest subsequence possible is 1 only. dp[i] represents the length of the longest subsequence that can be formed with a[i] as the starting element.
- Iterate from the n-2, and for every number multiply it with all the primes till it exceeds a[n-1] and perform the below operations.
- Multiply the number a[i] with prime to get x. If x exists in the hash-map then the recurrence will be dp[i] = max(dp[i], 1 + dp[hash[x]]).
- At the end, iterate in dp[] array and find the maximum value which will be our answer.
Below is the implementation of the above approach:
// C++ program to implement the // above approach #include <bits/stdc++.h> using namespace std;
// Function to pre-store primes void SieveOfEratosthenes( int MAX, vector< int >& primes)
{ bool prime[MAX + 1];
memset (prime, true , sizeof (prime));
// Sieve method to check if prime or not
for ( long long p = 2; p * p <= MAX; p++) {
if (prime[p] == true ) {
// Multiples
for ( long long i = p * p; i <= MAX; i += p)
prime[i] = false ;
}
}
// Pre-store all the primes
for ( long long i = 2; i <= MAX; i++) {
if (prime[i])
primes.push_back(i);
}
} // Function to find the longest subsequence int findLongest( int A[], int n)
{ // Hash map
unordered_map< int , int > mpp;
vector< int > primes;
// Call the function to pre-store the primes
SieveOfEratosthenes(A[n - 1], primes);
int dp[n];
memset (dp, 0, sizeof dp);
// Initialize last element with 1
// as that is the longest possible
dp[n - 1] = 1;
mpp[A[n - 1]] = n - 1;
// Iterate from the back and find the longest
for ( int i = n - 2; i >= 0; i--) {
// Get the number
int num = A[i];
// Initialize dp[i] as 1
// as the element will only me in
// the subsequence .
dp[i] = 1;
int maxi = 0;
// Iterate in all the primes and
// multiply to get the next element
for ( auto it : primes) {
// Next element if multiplied with it
int xx = num * it;
// If exceeds the last element
// then break
if (xx > A[n - 1])
break ;
// If the number is there in the array
else if (mpp[xx] != 0) {
// Get the maximum most element
dp[i] = max(dp[i], 1 + dp[mpp[xx]]);
}
}
// Hash the element
mpp[A[i]] = i;
}
int ans = 1;
// Find the longest
for ( int i = 0; i < n; i++) {
ans = max(ans, dp[i]);
}
return ans;
} // Driver Code int main()
{ int a[] = { 1, 2, 5, 6, 12, 35, 60, 385 };
int n = sizeof (a) / sizeof (a[0]);
cout << findLongest(a, n);
} |
// Java program to implement the // above approach import java.util.HashMap;
import java.util.Vector;
class GFG
{ // Function to pre-store primes
public static void SieveOfEratosthenes( int MAX,
Vector<Integer> primes)
{
boolean [] prime = new boolean [MAX + 1 ];
for ( int i = 0 ; i < MAX + 1 ; i++)
prime[i] = true ;
// Sieve method to check if prime or not
for ( int p = 2 ; p * p <= MAX; p++)
{
if (prime[p] == true )
{
// Multiples
for ( int i = p * p; i <= MAX; i += p)
prime[i] = false ;
}
}
// Pre-store all the primes
for ( int i = 2 ; i <= MAX; i++)
{
if (prime[i])
primes.add(i);
}
}
// Function to find the intest subsequence
public static int findLongest( int [] A, int n)
{
// Hash map
HashMap<Integer, Integer> mpp = new HashMap<>();
Vector<Integer> primes = new Vector<>();
// Call the function to pre-store the primes
SieveOfEratosthenes(A[n - 1 ], primes);
int [] dp = new int [n];
// Initialize last element with 1
// as that is the intest possible
dp[n - 1 ] = 1 ;
mpp.put(A[n - 1 ], n - 1 );
// Iterate from the back and find the intest
for ( int i = n - 2 ; i >= 0 ; i--)
{
// Get the number
int num = A[i];
// Initialize dp[i] as 1
// as the element will only me in
// the subsequence .
dp[i] = 1 ;
int maxi = 0 ;
// Iterate in all the primes and
// multiply to get the next element
for ( int it : primes)
{
// Next element if multiplied with it
int xx = num * it;
// If exceeds the last element
// then break
if (xx > A[n - 1 ])
break ;
// If the number is there in the array
else if (mpp.get(xx) != null && mpp.get(xx) != 0 )
{
// Get the maximum most element
dp[i] = Math.max(dp[i], 1 + dp[mpp.get(xx)]);
}
}
// Hash the element
mpp.put(A[i], i);
}
int ans = 1 ;
// Find the intest
for ( int i = 0 ; i < n; i++)
ans = Math.max(ans, dp[i]);
return ans;
}
// Driver code
public static void main(String[] args)
{
int [] a = { 1 , 2 , 5 , 6 , 12 , 35 , 60 , 385 };
int n = a.length;
System.out.println(findLongest(a, n));
}
} // This code is contributed by // sanjeev2552 |
# Python3 program to implement the # above approach from math import sqrt
# Function to pre-store primes def SieveOfEratosthenes( MAX , primes) :
prime = [ True ] * ( MAX + 1 );
# Sieve method to check if prime or not
for p in range ( 2 , int (sqrt( MAX )) + 1 ) :
if (prime[p] = = True ) :
# Multiples
for i in range (p * * 2 , MAX + 1 , p) :
prime[i] = False ;
# Pre-store all the primes
for i in range ( 2 , MAX + 1 ) :
if (prime[i]) :
primes.append(i);
# Function to find the longest subsequence def findLongest(A, n) :
# Hash map
mpp = {};
primes = [];
# Call the function to pre-store the primes
SieveOfEratosthenes(A[n - 1 ], primes);
dp = [ 0 ] * n ;
# Initialize last element with 1
# as that is the longest possible
dp[n - 1 ] = 1 ;
mpp[A[n - 1 ]] = n - 1 ;
# Iterate from the back and find the longest
for i in range (n - 2 , - 1 , - 1 ) :
# Get the number
num = A[i];
# Initialize dp[i] as 1
# as the element will only me in
# the subsequence
dp[i] = 1 ;
maxi = 0 ;
# Iterate in all the primes and
# multiply to get the next element
for it in primes :
# Next element if multiplied with it
xx = num * it;
# If exceeds the last element
# then break
if (xx > A[n - 1 ]) :
break ;
# If the number is there in the array
elif xx in mpp :
# Get the maximum most element
dp[i] = max (dp[i], 1 + dp[mpp[xx]]);
# Hash the element
mpp[A[i]] = i;
ans = 1 ;
# Find the longest
for i in range (n) :
ans = max (ans, dp[i]);
return ans;
# Driver Code if __name__ = = "__main__" :
a = [ 1 , 2 , 5 , 6 , 12 , 35 , 60 , 385 ];
n = len (a);
print (findLongest(a, n));
# This code is contributed by AnkitRai01 |
// C# program to implement the // above approach using System;
using System.Collections.Generic;
class GFG
{ // Function to pre-store primes
public static void SieveOfEratosthenes( int MAX,
List< int > primes)
{
Boolean[] prime = new Boolean[MAX + 1];
for ( int i = 0; i < MAX + 1; i++)
prime[i] = true ;
// Sieve method to check if prime or not
for ( int p = 2; p * p <= MAX; p++)
{
if (prime[p] == true )
{
// Multiples
for ( int i = p * p; i <= MAX; i += p)
prime[i] = false ;
}
}
// Pre-store all the primes
for ( int i = 2; i <= MAX; i++)
{
if (prime[i])
primes.Add(i);
}
}
// Function to find the intest subsequence
public static int findLongest( int [] A, int n)
{
// Hash map
Dictionary< int , int > mpp = new Dictionary< int , int >();
List< int > primes = new List< int >();
// Call the function to pre-store the primes
SieveOfEratosthenes(A[n - 1], primes);
int [] dp = new int [n];
// Initialize last element with 1
// as that is the intest possible
dp[n - 1] = 1;
mpp.Add(A[n - 1], n - 1);
// Iterate from the back and find the intest
for ( int i = n - 2; i >= 0; i--)
{
// Get the number
int num = A[i];
// Initialize dp[i] as 1
// as the element will only me in
// the subsequence .
dp[i] = 1;
// Iterate in all the primes and
// multiply to get the next element
foreach ( int it in primes)
{
// Next element if multiplied with it
int xx = num * it;
// If exceeds the last element
// then break
if (xx > A[n - 1])
break ;
// If the number is there in the array
else if (mpp.ContainsKey(xx) && mpp[xx] != 0)
{
// Get the maximum most element
dp[i] = Math.Max(dp[i], 1 + dp[mpp[xx]]);
}
}
// Hash the element
if (mpp.ContainsKey(A[i]))
mpp[A[i]] = i;
else
mpp.Add(A[i], i);
}
int ans = 1;
// Find the intest
for ( int i = 0; i < n; i++)
ans = Math.Max(ans, dp[i]);
return ans;
}
// Driver code
public static void Main(String[] args)
{
int [] a = { 1, 2, 5, 6, 12, 35, 60, 385 };
int n = a.Length;
Console.WriteLine(findLongest(a, n));
}
} // This code is contributed by Rajput-Ji |
5
Time Complexity: O(N log N)
Auxiliary Space: O(N)
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.