给定一个整数K和一个非负数组arr [] ,任务是找到乘积≤K的子序列数。
这个问题已经有了动态编程解决方案。该解决方案旨在为该问题提供优化的递归策略。
例子:
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
方法:通过执行转换arr [i] = log(arr [i])和K = log(K),将乘积问题转换为总和问题。生成所有子集,并存储已在子序列中获取的元素的总和。如果在任何时候总和大于K,那么我们知道,如果在子序列中添加另一个元素,则其总和也将大于K。因此,我们丢弃总和大于K的所有此类子序列,而无需对其进行递归调用。同样,如果我们当前的总和小于K,那么我们检查是否有机会进一步丢弃任何子序列。如果无法丢弃任何其他子序列,则不会进行任何递归调用。
下面是上述方法的实现:
C++
// C++ implementation of the above approach.
#include
#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 * 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#
// 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
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
?>
输出:
9