Skip to content
Related Articles

Related Articles

Count all sub-sequences having product <= K – Recursive approach
  • Difficulty Level : Medium
  • Last Updated : 16 Dec, 2019

Given an integer K and a non negative array arr[], the task is to find the number of sub-sequences having product ≤ K.
This problem already has a dynamic programming solution. This solution aims to provide an optimized recursive strategy to the problem.

Examples:

Input: arr[] = { 1, 2, 3, 4 }, K = 10
Output: 11
The sub-sequences are {1}, {2}, {3}, {4}, {1, 2}, {1, 3}, {1, 4}, {2, 3}, {2, 4}, {1, 2, 3}, {1, 2, 4}

Input: arr[] = { 4, 8, 7, 2 }, K = 50
Output: 9

Approach: Convert the product problem to a sum problem by performing the conversions arr[i] = log(arr[i]) and K = log(K). Generate all subsets and store the sum of elements that have been taken in the sub-sequence. If at any point, the sum becomes larger than K, then we know that if we add another element to the sub-sequence, its sum will also be larger than K. Therefore, we discard all such sub-sequences that have sum larger than K without making a recursive call for them. Also if we currently have sum less than K then we check if there are any chances to further discard any sub-sequences. If any further sub-sequences can’t be discarded then no recursive calls are made.



Below is the implementation of the above approach:

C++




// C++ implementation of the above approach.
#include <bits/stdc++.h>
  
#define ll long long
  
using namespace std;
  
// This variable counts discarded subsequences
ll discard_count = 0;
  
// Function to return a^n
ll power(ll a, ll n)
{
    if (n == 0)
        return 1;
    ll p = power(a, n / 2);
    p = p * p;
    if (n & 1)
        p = p * a;
    return p;
}
  
// Recursive function that counts discarded 
// subsequences
void solve(int i, int n, float sum, float k,
                   float* a, float* prefix)
{
  
    // If at any stage, sum > k
    // discard further subsequences
    if (sum > k) {
        discard_count += power(2, n - i);
  
        // Recursive call terminated
        // No further calls
        return;
    }
  
    if (i == n)
        return;
  
    // rem = Sum of array[i+1...n-1]
    float rem = prefix[n - 1] - prefix[i];
  
    // If there are chances of discarding 
    // further subsequences then make a
    // recursive call, otherwise not
    // Including a[i]
    if (sum + a[i] + rem > k)
        solve(i + 1, n, sum + a[i], k,
                          a, prefix);
  
    // Excluding a[i]
    if (sum + rem > k)
        solve(i + 1, n, sum, k, a, prefix);
}
  
// Function to return count of non-empty 
// subsequences whose product doesn't
// exceed k
int countSubsequences(const int* arr, 
                         int n, ll K)
{
    float sum = 0.0;
  
    // Converting k to log(k)
    float k = log2(K);
  
    // Prefix sum array and array to
    // store log values.
    float prefix[n], a[n];
  
    // a[] is the array obtained
    // after converting numbers to 
    // logarithms
    for (int i = 0; i < n; i++) {
        a[i] = log2(arr[i]);
        sum += a[i];
    }
  
    // Computing prefix sums
    prefix[0] = a[0];
    for (int i = 1; i < n; i++) {
        prefix[i] = prefix[i - 1] + a[i];
    }
  
    // Calculate non-empty subsequences
    // hence 1 is subtracted
    ll total = power(2, n) - 1;
  
    // If total sum is <= k, then 
    // answer = 2^n - 1
    if (sum <= k) {
        return total;
    }
  
    solve(0, n, 0.0, k, a, prefix);
    return total - discard_count;
}
  
// Driver code
int main()
{
    int arr[] = { 4, 8, 7, 2 };
    int n = sizeof(arr) / sizeof(arr[0]);
    ll k = 50;
    cout << countSubsequences(arr, n, k);
    return 0;
}

Java




// Java implementation of the above approach.
class GFG
{
  
// This variable counts discarded subsequences
static long discard_count = 0;
  
// Function to return a^n
static long power(long a, long n)
{
    if (n == 0)
        return 1;
    long p = power(a, n / 2);
    p = p * p;
    if (n % 2 == 1)
        p = p * a;
    return p;
}
  
// Recursive function that counts discarded 
// subsequences
static void solve(int i, int n, float sum, float k,
                float []a, float []prefix)
{
  
    // If at any stage, sum > k
    // discard further subsequences
    if (sum > k) 
    {
        discard_count += power(2, n - i);
  
        // Recursive calong terminated
        // No further calongs
        return;
    }
  
    if (i == n)
        return;
  
    // rem = Sum of array[i+1...n-1]
    float rem = prefix[n - 1] - prefix[i];
  
    // If there are chances of discarding 
    // further subsequences then make a
    // recursive calong, otherwise not
    // Including a[i]
    if (sum + a[i] + rem > k)
        solve(i + 1, n, sum + a[i], k,
                        a, prefix);
  
    // Excluding a[i]
    if (sum + rem > k)
        solve(i + 1, n, sum, k, a, prefix);
}
  
// Function to return count of non-empty 
// subsequences whose product doesn't
// exceed k
static int countSubsequences(int []arr, 
                        int n, long K)
{
    float sum = 0.0f;
  
    // Converting k to log(k)
    float k = (float) Math.log(K);
  
    // Prefix sum array and array to
    // store log values.
    float []prefix = new float[n];
    float []a = new float[n];
  
    // a[] is the array obtained
    // after converting numbers to 
    // logarithms
    for (int i = 0; i < n; i++)
    {
        a[i] = (float) Math.log(arr[i]);
        sum += a[i];
    }
  
    // Computing prefix sums
    prefix[0] = a[0];
    for (int i = 1; i < n; i++)
    {
        prefix[i] = prefix[i - 1] + a[i];
    }
  
    // Calculate non-empty subsequences
    // hence 1 is subtracted
    long total = power(2, n) - 1;
  
    // If total sum is <= k, then 
    // answer = 2^n - 1
    if (sum <= k) 
    {
        return (int) total;
    }
  
    solve(0, n, 0.0f, k, a, prefix);
    return (int) (total - discard_count);
}
  
// Driver code
public static void main(String[] args)
{
    int arr[] = { 4, 8, 7, 2 };
    int n = arr.length;
    long k = 50;
    System.out.print(countSubsequences(arr, n, k));
}
}
  
// This code is contributed by Rajput-Ji

Python3




# Python3 implementation of the 
# above approach. 
  
# From math lib import log2
from math import log2
  
# This variable counts discarded
# subsequences 
discard_count = 0
  
# Function to return a^n 
def power(a, n) :
      
    if (n == 0) :
        return 1
          
    p = power(a, n // 2)
    p = p * p
    if (n & 1) :
        p = p *
    return
  
# Recursive function that counts 
# discarded subsequences 
def solve(i, n, sum, k, a, prefix) :
    global discard_count
      
    # If at any stage, sum > k
    # discard further subsequences
    if (sum > k) :
        discard_count += power(2, n - i)
          
        # Recursive call terminated
        # No further calls 
        return
      
    if (i == n) :
        return
      
    # rem = Sum of array[i+1...n-1]
    rem = prefix[n - 1] - prefix[i]
      
    # If there are chances of discarding
    # further subsequences then make a 
    # recursive call, otherwise not 
    # Including a[i]
    if (sum + a[i] + rem > k) :
        solve(i + 1, n, sum + a[i], k, a, prefix) 
      
    # Excluding a[i] 
    if (sum + rem > k) :
        solve(i + 1, n, sum, k, a, prefix)
  
# Function to return count of non-empty 
# subsequences whose product doesn't 
# exceed k 
def countSubsequences(arr, n, K) :
      
    sum = 0.0
  
    # Converting k to log(k) 
    k = log2(K)
  
    # Prefix sum array and array to 
    # store log values. 
    prefix = [0] * n
    a = [0] * n
  
    # a[] is the array obtained after 
    # converting numbers to logarithms 
    for i in range(n) : 
        a[i] = log2(arr[i]) 
        sum += a[i]
      
    # Computing prefix sums 
    prefix[0] = a[0]
      
    for i in range(1, n) : 
        prefix[i] = prefix[i - 1] + a[i]
  
    # Calculate non-empty subsequences 
    # hence 1 is subtracted 
    total = power(2, n) - 1
  
    # If total sum is <= k, then 
    # answer = 2^n - 1 
    if (sum <= k) : 
        return total
  
    solve(0, n, 0.0, k, a, prefix)
    return total - discard_count 
  
# Driver code 
if __name__ == "__main__" :
  
    arr = [ 4, 8, 7, 2
    n = len(arr)
    k = 50
    print(countSubsequences(arr, n, k))
  
# This code is contributed by Ryuga

C#




// C# implementation of the above approach.
using System;
  
class GFG
{
  
// This variable counts discarded subsequences
static long discard_count = 0;
  
// Function to return a^n
static long power(long a, long n)
{
    if (n == 0)
        return 1;
    long p = power(a, n / 2);
    p = p * p;
    if (n % 2 == 1)
        p = p * a;
    return p;
}
  
// Recursive function that counts discarded 
// subsequences
static void solve(int i, int n, float sum, float k,
                     float []a, float []prefix)
{
  
    // If at any stage, sum > k
    // discard further subsequences
    if (sum > k) 
    {
        discard_count += power(2, n - i);
  
        // Recursive calong terminated
        // No further calongs
        return;
    }
  
    if (i == n)
        return;
  
    // rem = Sum of array[i+1...n-1]
    float rem = prefix[n - 1] - prefix[i];
  
    // If there are chances of discarding 
    // further subsequences then make a
    // recursive calong, otherwise not
    // Including a[i]
    if (sum + a[i] + rem > k)
        solve(i + 1, n, sum + a[i], k,
                           a, prefix);
  
    // Excluding a[i]
    if (sum + rem > k)
        solve(i + 1, n, sum, k, a, prefix);
}
  
// Function to return count of non-empty 
// subsequences whose product doesn't
// exceed k
static int countSubsequences(int []arr, 
                             int n, long K)
{
    float sum = 0.0f;
  
    // Converting k to log(k)
    float k = (float) Math.Log(K);
  
    // Prefix sum array and array to
    // store log values.
    float []prefix = new float[n];
    float []a = new float[n];
  
    // []a is the array obtained
    // after converting numbers to 
    // logarithms
    for (int i = 0; i < n; i++)
    {
        a[i] = (float) Math.Log(arr[i]);
        sum += a[i];
    }
  
    // Computing prefix sums
    prefix[0] = a[0];
    for (int i = 1; i < n; i++)
    {
        prefix[i] = prefix[i - 1] + a[i];
    }
  
    // Calculate non-empty subsequences
    // hence 1 is subtracted
    long total = power(2, n) - 1;
  
    // If total sum is <= k, then 
    // answer = 2^n - 1
    if (sum <= k) 
    {
        return (int) total;
    }
  
    solve(0, n, 0.0f, k, a, prefix);
    return (int) (total - discard_count);
}
  
// Driver code
public static void Main(String[] args)
{
    int []arr = { 4, 8, 7, 2 };
    int n = arr.Length;
    long k = 50;
    Console.Write(countSubsequences(arr, n, k));
}
}
  
// This code is contributed by Rajput-Ji

PHP




<?php 
// PHP implementation of the above approach.
  
// This variable counts discarded subsequences
$discard_count = 0;
  
// Function to return a^n
function power($a, $n)
{
    if ($n == 0)
        return 1;
    $p = power($a, $n / 2);
    $p = $p * $p;
    if ($n & 1)
        $p = $p * $a;
    return $p;
}
  
// Recursive function that counts discarded 
// subsequences
function solve($i, $n, $sum, $k, &$a, &$prefix)
{
    global $discard_count;
  
    // If at any stage, sum > k
    // discard further subsequences
    if ($sum > $k
    {
        $discard_count += power(2, $n - $i);
  
        // Recursive call terminated
        // No further calls
        return;
    }
  
    if ($i == $n)
        return;
  
    // rem = Sum of array[i+1...n-1]
    $rem = $prefix[$n - 1] - $prefix[$i];
  
    // If there are chances of discarding 
    // further subsequences then make a
    // recursive call, otherwise not
    // Including a[i]
    if ($sum + $a[$i] + $rem > $k)
        solve($i + 1, $n, $sum + $a[$i], $k,
                               $a, $prefix);
  
    // Excluding a[i]
    if ($sum + $rem > $k)
        solve($i + 1, $n, $sum, $k, $a, $prefix);
}
  
// Function to return count of non-empty 
// subsequences whose product doesn't
// exceed k
function countSubsequences(&$arr, $n, $K)
{
    global $discard_count;
    $sum = 0.0;
  
    // Converting k to log(k)
    $k = log($K, 2);
  
    // Prefix sum array and array to
    // store log values.
    $prefix = array_fill(0, $n, NULL);
    $a = array_fill(0, $n, NULL);
  
    // a[] is the array obtained after 
    // converting numbers to logarithms
    for ($i = 0; $i < $n; $i++) 
    {
        $a[$i] = log($arr[$i], 2);
        $sum += $a[$i];
    }
  
    // Computing prefix sums
    $prefix[0] = $a[0];
    for ($i = 1; $i < $n; $i++) 
    {
        $prefix[$i] = $prefix[$i - 1] + $a[$i];
    }
  
    // Calculate non-empty subsequences
    // hence 1 is subtracted
    $total = power(2, $n) - 1;
  
    // If total sum is <= k, then 
    // answer = 2^n - 1
    if ($sum <= $k
    {
        return $total;
    }
  
    solve(0, $n, 0.0, $k, $a, $prefix);
    return $total - $discard_count;
}
  
// Driver code
$arr = array(4, 8, 7, 2 );
$n = sizeof($arr);
$k = 50;
echo countSubsequences($arr, $n, $k);
  
// This code is contributed by ita_c
?>
Output:
9

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.  To complete your preparation from learning a language to DS Algo and many more,  please refer Complete Interview Preparation Course.

In case you wish to attend live classes with industry experts, please refer Geeks Classes Live and Geeks Classes Live USA

My Personal Notes arrow_drop_up
Recommended Articles
Page :