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

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++

filter_none

edit
close

play_arrow

link
brightness_4
code

// C++ program to implement the
// above approach
#include <bits/stdc++.h>
using namespace std;
  
// Fucntion 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);
}

chevron_right


Java

filter_none

edit
close

play_arrow

link
brightness_4
code

// Java program to implement the 
// above approach
import java.util.HashMap;
import java.util.Vector;
  
class GFG 
{
  
    // Fucntion 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

chevron_right


Python3

filter_none

edit
close

play_arrow

link
brightness_4
code

# Python3 program to implement the 
# above approach 
  
from math import sqrt
  
# Fucntion 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

chevron_right


C#

filter_none

edit
close

play_arrow

link
brightness_4
code

// C# program to implement the 
// above approach
using System;
using System.Collections.Generic; 
  
class GFG 
{
  
    // Fucntion 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

chevron_right


Output:

5

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



My Personal Notes arrow_drop_up

Striver(underscore)79 at Codechef and codeforces D

If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.