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 4Â
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.
- 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:Â
C++
#include <bits/stdc++.h>using namespace std;Â
// Function to check if a number is prime or notbool 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 subsequenceint 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;} |
Java
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));    }} |
Python3
# Function to check if a number is prime or notdef 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 subsequencedef 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)) |
C#
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));    }} |
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++
// C++ program to implement the// above approach#include <bits/stdc++.h>using namespace std;Â
// Function to pre-store primesvoid 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 subsequenceint 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 Codeint main(){    int a[] = { 1, 2, 5, 6, 12, 35, 60, 385 };    int n = sizeof(a) / sizeof(a[0]);    cout << findLongest(a, n);} |
Java
// Java program to implement the // above approachimport 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
# 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#
// C# program to implement the // above approachusing 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 |
Javascript
<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)
Â
Ready to dive in? Explore our Free Demo Content and join our DSA course, trusted by over 100,000 zambiatek!



