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*3
2 and 3 are primesInput: a[] = {1, 2, 5, 6, 12, 35, 60, 385}
Output: 5
Brute Force Approach: The brute force approach for solving the problem of finding the length of the longest subsequence in an array where each element is a factor of the next element and the quotient is a prime number involves iterating over the array and for each element, iterating over all the elements after it to find the elements that are multiples of the current element and have a prime quotient. If such an element is found, the length of the subsequence starting from the current element is updated by adding 1 to the length of the subsequence starting from the element that satisfies the condition. The maximum length of all such subsequences is then returned as the answer.
- Initialize an array dp with all values set to 0.
- Initialize dp[n-1] to 1 since the last element is always part of the subsequence.
- Iterate over the array from the second last element to the first element.
- For each element, iterate over all the elements after it and check if the current element is a divisor of the next element and if the quotient is a prime number.
- If both conditions are true, update the value of dp[i] with the maximum of dp[j] (where j is the index of the element that satisfies the conditions).
- Once all the iterations are complete, find the maximum value in the dp array and return it as the answer.
Below is the implementation of the above approach:
#include <bits/stdc++.h> using namespace std;
// Function to check if a number is prime or not bool isPrime( int num)
{ if (num <= 1)
return false ;
for ( int i = 2; i * i <= num; i++) {
if (num % i == 0)
return false ;
}
return true ;
} // Function to find the longest subsequence int findLongest( int A[], int n)
{ // Initialize the dp array with all values set to 0
int dp[n];
memset (dp, 0, sizeof dp);
// Initialize dp[n-1] to 1 since the last element is
// always part of the subsequence
dp[n - 1] = 1;
// Iterate over the array from the second last element
// to the first element
for ( int i = n - 2; i >= 0; i--) {
// Get the current element
int num = A[i];
// Initialize dp[i] to 1 as the current element is
// always part of the subsequence
dp[i] = 1;
// Initialize maxi to 0
int maxi = 0;
// Iterate over all the elements after i and check
// if the current element is a divisor of the next
// element and if the quotient is a prime number
for ( int j = i + 1; j < n; j++) {
if (A[j] % num == 0 && isPrime(A[j] / num)) {
// If both conditions are true, update maxi
// with the maximum value of dp[j]
maxi = max(maxi, dp[j]);
}
}
// Update dp[i] with dp[j] + 1
dp[i] += maxi;
}
// Find the maximum value in the dp array and return it
// as the answer
int ans = 1;
for ( int i = 0; i < n; i++) {
ans = max(ans, dp[i]);
}
return ans;
} int main()
{ int a[] = { 1, 2, 5, 6, 12, 35, 60, 385 };
int n = sizeof (a) / sizeof (a[0]);
cout << findLongest(a, n);
return 0;
} |
import java.util.Arrays;
public class Main {
// Function to check if a number is prime or not
static boolean isPrime( int num)
{
if (num <= 1 )
return false ;
for ( int i = 2 ; i * i <= num; i++) {
if (num % i == 0 )
return false ;
}
return true ;
}
// Function to find the longest subsequence
static int findLongest( int [] A, int n)
{
// Initialize the dp array with all values set to 0
int [] dp = new int [n];
Arrays.fill(dp, 0 );
// Initialize dp[n-1] to 1 since the last element is
// always part of the subsequence
dp[n - 1 ] = 1 ;
// Iterate over the array from the second last
// element to the first element
for ( int i = n - 2 ; i >= 0 ; i--) {
// Get the current element
int num = A[i];
// Initialize dp[i] to 1 as the current element
// is always part of the subsequence
dp[i] = 1 ;
// Initialize maxi to 0
int maxi = 0 ;
// Iterate over all the elements after i and
// check if the current element is a divisor of
// the next element and if the quotient is a
// prime number
for ( int j = i + 1 ; j < n; j++) {
if (A[j] % num == 0
&& isPrime(A[j] / num)) {
// If both conditions are true, update
// maxi with the maximum value of dp[j]
maxi = Math.max(maxi, dp[j]);
}
}
// Update dp[i] with dp[j] + 1
dp[i] += maxi;
}
// Find the maximum value in the dp array and return
// it as the answer
int ans = 1 ;
for ( int i = 0 ; i < n; i++) {
ans = Math.max(ans, dp[i]);
}
return ans;
}
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));
}
} |
# Function to check if a number is prime or not def is_prime(num):
if num < = 1 :
return False
for i in range ( 2 , int (num * * 0.5 ) + 1 ):
if num % i = = 0 :
return False
return True
# Function to find the longest subsequence def find_longest(A):
n = len (A)
# Initialize the dp list with all values set to 0
dp = [ 0 ] * n
# Initialize dp[n-1] to 1 since the last element is
# always part of the subsequence
dp[n - 1 ] = 1
# Iterate over the list from the second last element
# to the first element
for i in range (n - 2 , - 1 , - 1 ):
# Get the current element
num = A[i]
# Initialize dp[i] to 1 as the current element is
# always part of the subsequence
dp[i] = 1
# Initialize maxi to 0
maxi = 0
# Iterate over all the elements after i and check
# if the current element is a divisor of the next
# element and if the quotient is a prime number
for j in range (i + 1 , n):
if A[j] % num = = 0 and is_prime(A[j] / / num):
# If both conditions are true, update maxi
# with the maximum value of dp[j]
maxi = max (maxi, dp[j])
# Update dp[i] with dp[j] + 1
dp[i] + = maxi
# Find the maximum value in the dp list and return it
# as the answer
ans = 1
for i in range (n):
ans = max (ans, dp[i])
return ans
a = [ 1 , 2 , 5 , 6 , 12 , 35 , 60 , 385 ]
print (find_longest(a))
|
using System;
class Program
{ // Function to check if a number is prime or not
static bool IsPrime( int num)
{
if (num <= 1)
return false ;
for ( int i = 2; i * i <= num; i++)
{
if (num % i == 0)
return false ;
}
return true ;
}
// Function to find the longest subsequence
static int FindLongest( int [] A, int n)
{
// Initialize the dp array with all values set to 0
int [] dp = new int [n];
Array.Clear(dp, 0, n);
// Initialize dp[n-1] to 1 since the last element is always part of the subsequence
dp[n - 1] = 1;
// Iterate over the array from the second last element to the first element
for ( int i = n - 2; i >= 0; i--)
{
// Get the current element
int num = A[i];
// Initialize dp[i] to 1 as the current element is always part of the subsequence
dp[i] = 1;
// Initialize maxi to 0
int maxi = 0;
// Iterate over all the elements after i and check if the current element is a divisor of the next
// element and if the quotient is a prime number
for ( int j = i + 1; j < n; j++)
{
if (A[j] % num == 0 && IsPrime(A[j] / num))
{
// If both conditions are true, update maxi with the maximum value of dp[j]
maxi = Math.Max(maxi, dp[j]);
}
}
// Update dp[i] with dp[j] + 1
dp[i] += maxi;
}
// Find the maximum value in the dp array and return it as the answer
int ans = 1;
for ( int i = 0; i < n; i++)
{
ans = Math.Max(ans, dp[i]);
}
return ans;
}
static void Main()
{
int [] a = { 1, 2, 5, 6, 12, 35, 60, 385 };
int n = a.Length;
Console.WriteLine(FindLongest(a, n));
}
} |
// Function to check if a number is prime or not function isPrime(num) {
if (num <= 1) {
return false ;
}
for (let i = 2; i * i <= num; i++) {
if (num % i === 0) {
return false ;
}
}
return true ;
} // Function to find the longest subsequence function findLongest(A) {
const n = A.length;
// Initialize the dp array with all values set to 0
const dp = new Array(n).fill(0);
// Initialize dp[n-1] to 1 since the last element is always part of the subsequence
dp[n - 1] = 1;
// Iterate over the array from the second last element to the first element
for (let i = n - 2; i >= 0; i--) {
// Get the current element
const num = A[i];
// Initialize dp[i] to 1 as the current element is always part of the subsequence
dp[i] = 1;
// Initialize maxi to 0
let maxi = 0;
// Iterate over all the elements after i and check if the current element is a divisor
// of the next element and if the quotient is a prime number
for (let j = i + 1; j < n; j++) {
if (A[j] % num === 0 && isPrime(A[j] / num)) {
// If both conditions are true, update maxi with the maximum value of dp[j]
maxi = Math.max(maxi, dp[j]);
}
}
// Update dp[i] with dp[j] + 1
dp[i] += maxi;
}
// Find the maximum value in the dp array and return it as the answer
let ans = 1;
for (let i = 0; i < n; i++) {
ans = Math.max(ans, dp[i]);
}
return ans;
} // Example usage const a = [1, 2, 5, 6, 12, 35, 60, 385]; console.log(findLongest(a)); |
Output:
5
Time Complexity: O(N * N)
Auxiliary Space: O(N)
Efficient 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, they store all the primes in any of the data structures.
- 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 n-2, and for every number multiply it with all the primes till it exceeds a[n-1] and performs the operations below.
- 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]]).
- In 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 |
<script> // Javascript program to implement the
// above approach
// Function to pre-store primes
function SieveOfEratosthenes(MAX, primes) {
let prime = new Array(MAX + 1).fill( true );
// Sieve method to check if prime or not
for (let p = 2; p * p <= MAX; p++) {
if (prime[p] == true ) {
// Multiples
for (let i = p * p; i <= MAX; i += p)
prime[i] = false ;
}
}
// Pre-store all the primes
for (let i = 2; i <= MAX; i++) {
if (prime[i])
primes.push(i);
}
}
// Function to find the longest subsequence
function findLongest(A, n) {
// Hash map
let mpp = new Map();
let primes = new Array();
// Call the function to pre-store the primes
SieveOfEratosthenes(A[n - 1], primes);
let dp = new Array(n);
dp.fill(0)
// Initialize last element with 1
// as that is the longest possible
dp[n - 1] = 1;
mpp.set(A[n - 1], n - 1);
// Iterate from the back and find the longest
for (let i = n - 2; i >= 0; i--) {
// Get the number
let num = A[i];
// Initialize dp[i] as 1
// as the element will only me in
// the subsequence .
dp[i] = 1;
let maxi = 0;
// Iterate in all the primes and
// multiply to get the next element
for (let it of primes) {
// Next element if multiplied with it
let 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)) {
// Get the maximum most element
dp[i] = Math.max(dp[i], 1 + dp[mpp.get(xx)]);
}
}
// Hash the element
mpp.set(A[i], i);
}
let ans = 1;
// Find the longest
for (let i = 0; i < n; i++) {
ans = Math.max(ans, dp[i]);
}
return ans;
}
// Driver Code
let a = [1, 2, 5, 6, 12, 35, 60, 385];
let n = a.length;
document.write(findLongest(a, n));
// This code is contributed by _saurabh_jaiswal </script> |
5
Time Complexity: O(N log N)
Auxiliary Space: O(N)