Open In App

Longest subsequence such that every element in the subsequence is formed by multiplying previous element with a prime

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
The longest subsequence is {3, 6, 12, 36} 
6 = 3*2 
12 = 6*2 
36 = 12*3 
2 and 3 are primes 

Input: 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.

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:  

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>

Output
5




Time Complexity: O(N log N) 
Auxiliary Space: O(N)
 


Article Tags :