Given an integer K and a non-negative array arr[], the task is to find the number of sub-sequences having the 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++ 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 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 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 * a
return p
# 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# 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 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 ?> |
<script> // Javascript implementation of the above approach. // This variable counts discarded subsequences let discard_count = 0; // Function to return a^n function power(a,n)
{ if (n == 0)
return 1;
let p = power(a, Math.floor(n / 2));
p = p * p;
if (n % 2 == 1)
p = p * a;
return p;
} // Recursive function that counts discarded // subsequences function solve(i,n,sum,k,a,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]
let 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 function countSubsequences(arr,n,K)
{ let sum = 0.0;
// Converting k to log(k)
let k = Math.log(K);
// Prefix sum array and array to
// store log values.
let prefix = new Array(n);
let a = new Array(n);
// a[] is the array obtained
// after converting numbers to
// logarithms
for (let i = 0; i < n; i++)
{
a[i] = Math.log(arr[i]);
sum += a[i];
}
// Computing prefix sums
prefix[0] = a[0];
for (let i = 1; i < n; i++)
{
prefix[i] = prefix[i - 1] + a[i];
}
// Calculate non-empty subsequences
// hence 1 is subtracted
let 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 let arr=[4, 8, 7, 2]; let n = arr.length; let k = 50; document.write(countSubsequences(arr, n, k)); // This code is contributed by avanitrachhadiya2155 </script> |
9