Given a non-negative array, find the number of subsequences having a product smaller than K.
Examples:
Input : [1, 2, 3, 4]
k = 10
Output :11
Input : [4, 8, 7, 2]
k = 50
Output : 9
So, We want to count the number of subsequences whose product is less than K.
There are sub-problems, and it can be solved using Dynamic Programming
However, I tried to write down the recursive code for better understanding.
Note: I am getting an answer as 6, which is wrong.
Can someone help me, How to foresee the correct Logic?
#include <bits/stdc++.h>
using namespace std;
vector<int> A{1, 2, 3, 4};
int countSubsequence(int i, int prod, int K)
{
if(prod > 1 && prod <= K)
return 1;
if(i >= A.size() || prod > K)
return 0;
return countSubsequence(i + 1, prod, K) + countSubsequence(i + 1, prod*A[i], K);
}
int main()
{
int K = 10;
cout << countSubsequence(0, 1, K);
return 0;
}
The condition
if(prod > 1 && prod <= K)
return 1;
will have it return from the function (for example) when [1, 2] is selected from [1, 2, 3, 4] and prevent it from searching for [1, 2, 3].
Also:
The condition prod <= K is wrong becasue you want the product smaller than K, not K or smaller.
You cannot distinguish "nothing is multiplied" and "only the number 1 is multiplied" when you use 1 as the initial value.
Try this:
#include <bits/stdc++.h>
using namespace std;
vector<int> A{1, 2, 3, 4};
int countSubsequence(int i, int prod, int K)
{
if(i >= A.size() && 0 <= prod && prod < K)
return 1;
if(i >= A.size() || prod >= K)
return 0;
return countSubsequence(i + 1, prod, K) + countSubsequence(i + 1, prod < 0 ? A[i] : prod*A[i], K);
}
int main()
{
int K = 10;
cout << countSubsequence(0, -1, K);
return 0;
}
Related
Given an array A of integers N, and after inputting the integers into the array, I need to make the difference between the neighboring less or equal to D and we need to do that in minimal moves. In the end print out the sum of the numbers that have been added or subtracted.
For every 0 < i < N, |S[i] - S[i - 1]| <= D
You can increase and decrease the number of the array element
Example 1: If we have an array like this
N = 7, D = 3 [2, 10, 2, 6, 4, 3, 3], then in this array we have to make the difference between the neighboring elements less or equal than 3. We don't modify the first array element, we skip over to the second array elements where we modify it from 10 down to 5 (since A[0] + 3 = 5), then we don't change the third element, we change the fourth element from 6 down to 5 (because A[3] + 3 = 5) and we don't change the rest of the elements because the difference between them is less than D. In the end we have to print out 6 (s = 0; 10 -> 5, s = 5; 6 -> 5, s = 6)
Example 2: If we have an array like this
N = 7, D = 0 [1, 4, 1, 2, 4, 2, 2]. Since D in this case is 0, by some logic we have to make all of the numbers the same. The most optimal (and in the fewest steps to solve this) way is we start with the last elements, we leave A[6] and A[5], we skip over to A[4]. Since A[4] is 4 and A[5] is 2, we have to change the 4 down to 2. Now since A[4] is 2, we skip over A[3] and we go to A[3] we change it from 1 up to 2. Then we change A[1] from 4 down to 2 and in the end, we change A[0] from 1 up to 2. In the end we have to print out 6 (s = 0; 4 -> 2, s = 2; 1 -> 2, s = 3; 4 -> 2, s = 5; 1 -> 2, s = 6).
Some other test cases:
N = 7, D = 1 [2, 10, 0, 2, 4, 3, 3] Solution: 10
N = 5, D = 1 [6, 5, 4, 3, 2] Solution: 0
I am unable to find an algorithm or an approach to this problem. I have tried several solutions and the closest I have come to solving it was 7/30 test cases.
My code:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
int main() {
int n, d, s1 = 0, s2 = 1;
cin >> n >> d;
int a[n], b[n];
for(int i = 0; i < n; i++) {
cin >> a[i];
b[i] = a[i];
}
reverse(b, b + n);
for(int i = 1; i < n; i++) {
if(a[i] - a[i - 1] <= d) {
continue;
} else {
if(a[i] > a[i - 1] + d) {
while(a[i] > a[i - 1] + d) {
a[i]--;
s1++;
}
} else if(a[i - 1] - d > a[i]) {
while(a[i - 1] - d > a[i]) {
a[i]++;
s1++;
}
}
}
}
for(int i = 1; i < n; i++) {
if(b[i] - b[i - 1] <= d) {
continue;
} else {
if(b[i] > b[i - 1] + d) {
while(b[i] > b[i - 1] + d) {
b[i]--;
s2++;
}
} else if(b[i - 1] - d > b[i]) {
while(b[i - 1] - d > b[i]) {
b[i]++;
s2++;
}
}
}
}
if(s1 >= s2)
cout << s2;
else
cout << s1;
return 0;
}
I studied the gap algorithm(merging without extra space) but after coding, it looks ok to me but it is not giving a correct answer or maybe an error, please check out my code and it would be very helpful if you guys can tell me what's wrong.
arr1 and arr2 are sorted arrays of n and m sizes respectively, I excluded the driver code.
main() function is just taking input of sorted arrays arr1 and arr2 and then after implementing the merge function it is printing the values of arr1 and arr2 which expected to be sorted as merged array
This is the algorithm - https://www.geeksforgeeks.org/efficiently-merging-two-sorted-arrays-with-o1-extra-space/
Example - arr1 = {1, 3, 5, 7}
arr2 = {0 , 2 , 6, 8, 9}
expected output - arr1 = {0,1,2,3}
arr2 = {5,6,7,8,9}
observed output - Nothing it just crashes.
void merge(int arr1[], int arr2[], int n, int m) {
int soa = (n+m);
int gap;
if(soa%2 == 0){
gap = soa/2;
}
else{
gap = (soa+1)/2;
}
for(int g = gap; g >= 1; g/2){
for(int i = 0; i < soa; i++){
int j = i + g;
if(j >= soa){
break;
}
if(j < n){
if(arr1[i] > arr1[j]){
swap(arr1[i],arr1[j]);
}
}
else if(j >= n && i < n){
if(arr1[i] > arr2[j - n]){
swap(arr1[i],arr2[j-n]);
}
}
else if(i >= n && j >= n){
if(arr2[i - n] > arr2[j - n]){
swap(arr2[i - n], arr2[j - n]);
}
}
}
}
}
decompose(11) must return [1,2,4,10].
Note that there are actually two ways to decompose 11², 11² = 121 = 1 + 4 + 16 + 100 = 1² + 2² + 4² + 10².
For decompose(50) don't return [1, 1, 4, 9, 49] but [1, 3, 5, 8, 49] since [1, 1, 4, 9, 49] doesn't form a strictly increasing sequence.
I created a function but in only some cases provides a strictly increasing sequence all of my solutions add up to the correct number, what changes do i have to make to enable the return of a strictly increasing sequence?
vector<ll> Decomp::decompose(ll n){
ll square = n * n, j = 1, nextterm = n - 1, remainder, sum = 0;
float root;
vector<ll> sequence;
do
{
sequence.push_back(nextterm);
sum = sum + (nextterm * nextterm);
remainder = square - sum;
root = sqrt(remainder - 1);
if (root - (int)root > 0)
{
root = (int)root;
}
j = 1;
nextterm = (int)root;
if (remainder == 1)
{
sequence.push_back(1);
}
} while (root > 0);
reverse(sequence.begin(),sequence.end());
for (int i=0; i < sequence.size(); i++)
{
cout << sequence[i] << endl;
}
}
Here is a simple recursive approach, basically exploring all the possibilities.
It stops once a solution is found.
Output:
11 : 1 2 4 10
50 : 1 3 5 8 49
And the code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
bool decompose_dp (long long int sum, long long int k, std::vector<long long int> &seq) {
while (k > 0) {
long long int sump = sum - k*k;
if (sump == 0) {
seq.push_back(k);
return true;
}
if (sump < 0) {
k--;
continue;
}
long long int kp = k-1;
while (kp > 0) {
if (decompose_dp(sump, kp, seq)) {
seq.push_back(k);
return true;
}
kp --;
}
k--;
}
return false;
}
std::vector<long long int> decompose(long long int n){
long long int square = n * n, j = 1, nextterm = n - 1, remainder, sum = 0;
float root;
std::vector<long long int> sequence;
auto check = decompose_dp (n*n, n-1, sequence);
return sequence;
}
void pr (long long int n, const std::vector<long long int> &vec) {
std::cout << n << " : ";
for (auto k: vec) {
std::cout << k << " ";
}
std::cout << "\n";
}
int main() {
long long int n = 11;
auto sequence = decompose (n);
pr (n, sequence);
n = 50;
sequence = decompose (n);
pr (n, sequence);
}
Here's BFS, DFS and brute force in Python. BFS seems slow for input 50. Brute force yielded 91020 different combinations for input 50.
from collections import deque
def bfs(n):
target = n * n
queue = deque([(target, [], 1)])
while queue:
t, seq, i = queue.popleft()
if t == 0:
return seq
if (t == target and i*i < t) or (t != target and i*i <= t):
queue.append((t - i*i, seq[:] + [i], i + 1))
queue.append((t, seq, i + 1))
def dfs(n):
target = n * n
stack = [(target, [], 1)]
while stack:
t, seq, i = stack.pop()
if t == 0:
return seq
if (t == target and i*i < t) or (t != target and i*i <= t):
stack.append((t - i*i, seq[:] + [i], i + 1))
stack.append((t, seq, i + 1))
def brute(n):
target = n * n
stack = [(target, [], 1)]
result = []
while stack:
t, seq, i = stack.pop()
if t == 0:
result.append(seq)
if (t == target and i*i < t) or (t != target and i*i <= t):
stack.append((t - i*i, seq[:] + [i], i + 1))
stack.append((t, seq, i + 1))
return result
print bfs(50) # [1, 2, 3, 4, 5, 6, 7, 8, 10, 11, 12, 13, 14, 15, 16, 18, 19, 20]
print dfs(50) # [30, 40]
#print brute(50)
#include <bits/stdc++.h>
using namespace std;
int MaximumSum(int A[], int low, int high)
{
if (high == low)
return A[low];
int mid = (low + high) / 2;
int leftMax = INT_MIN;
int sum = 0;
for (int i = mid; i >= low; i--)
{
sum += A[i];
if (sum > leftMax)
leftMax = sum;
}
/*
why not write this way? I know when coding like this, answer is wrong.
for (int i = low; i <= mid; i++)
{
sum += A[i];
if (sum > leftMax)
leftMax = sum;
}
*/
int rightMax = INT_MIN;
sum = 0; // reset sum to 0
for (int i = mid + 1; i <= high; i++)
{
sum += A[i];
if (sum > rightMax)
rightMax = sum;
}
int maxLeftRight = max(MaximumSum(A, low, mid),
MaximumSum(A, mid + 1, high));
return max(maxLeftRight, leftMax + rightMax);
}
int main()
{
int arr[] = { -2,1,-3,4,-1,2,1,-5,4 };
int n = sizeof(arr) / sizeof(arr[0]);
cout << "The Maximum sum of the subarray is " <<
MaximumSum(arr, 0, n - 1);
return 0;
}
my question is when solve leftMax, why not use for loop from low to mid,what's the difference between right version and wrong version, I know for loop in sequence is wrong, but I wonder why?I don't know why I can't submit...
You want to compute sub-array for middle point, so for the left part, you have to compute from right to left.
For example for
[5, -42, 2, 0, 1, 2, 3]
parts are
[5, -42, 2, 0] [1, 2, 3]
computing from left to right for [5, -42, 2, 0] gives 5
whereas computing from left to right gives 2
so the sub-array sum containing 0 (mid) is
[2, 0] + [1, 2, 3]
BTW, your algorithm is not optimal, it could be done in linear complexity.
Here I try to write a program in C++ to find NCR. But I've got a problem in the result. It is not correct. Can you help me find what the mistake is in the program?
#include <iostream>
using namespace std;
int fact(int n){
if(n==0) return 1;
if (n>0) return n*fact(n-1);
};
int NCR(int n,int r){
if(n==r) return 1;
if (r==0&&n!=0) return 1;
else return (n*fact(n-1))/fact(n-1)*fact(n-r);
};
int main(){
int n; //cout<<"Enter A Digit for n";
cin>>n;
int r;
//cout<<"Enter A Digit for r";
cin>>r;
int result=NCR(n,r);
cout<<result;
return 0;
}
Your formula is totally wrong, it's supposed to be fact(n)/fact(r)/fact(n-r), but that is in turn a very inefficient way to compute it.
See Fast computation of multi-category number of combinations and especially my comments on that question. (Oh, and please reopen that question also so I can answer it properly)
The single-split case is actually very easy to handle:
unsigned nChoosek( unsigned n, unsigned k )
{
if (k > n) return 0;
if (k * 2 > n) k = n-k;
if (k == 0) return 1;
int result = n;
for( int i = 2; i <= k; ++i ) {
result *= (n-i+1);
result /= i;
}
return result;
}
Demo: http://ideone.com/aDJXNO
If the result doesn't fit, you can calculate the sum of logarithms and get the number of combinations inexactly as a double. Or use an arbitrary-precision integer library.
I'm putting my solution to the other, closely related question here, because ideone.com has been losing code snippets lately, and the other question is still closed to new answers.
#include <utility>
#include <vector>
std::vector< std::pair<int, int> > factor_table;
void fill_sieve( int n )
{
factor_table.resize(n+1);
for( int i = 1; i <= n; ++i )
factor_table[i] = std::pair<int, int>(i, 1);
for( int j = 2, j2 = 4; j2 <= n; (j2 += j), (j2 += ++j) ) {
if (factor_table[j].second == 1) {
int i = j;
int ij = j2;
while (ij <= n) {
factor_table[ij] = std::pair<int, int>(j, i);
++i;
ij += j;
}
}
}
}
std::vector<unsigned> powers;
template<int dir>
void factor( int num )
{
while (num != 1) {
powers[factor_table[num].first] += dir;
num = factor_table[num].second;
}
}
template<unsigned N>
void calc_combinations(unsigned (&bin_sizes)[N])
{
using std::swap;
powers.resize(0);
if (N < 2) return;
unsigned& largest = bin_sizes[0];
size_t sum = largest;
for( int bin = 1; bin < N; ++bin ) {
unsigned& this_bin = bin_sizes[bin];
sum += this_bin;
if (this_bin > largest) swap(this_bin, largest);
}
fill_sieve(sum);
powers.resize(sum+1);
for( unsigned i = largest + 1; i <= sum; ++i ) factor<+1>(i);
for( unsigned bin = 1; bin < N; ++bin )
for( unsigned j = 2; j <= bin_sizes[bin]; ++j ) factor<-1>(j);
}
#include <iostream>
#include <cmath>
int main(void)
{
unsigned bin_sizes[] = { 8, 1, 18, 19, 10, 10, 7, 18, 7, 2, 16, 8, 5, 8, 2, 3, 19, 19, 12, 1, 5, 7, 16, 0, 1, 3, 13, 15, 13, 9, 11, 6, 15, 4, 14, 4, 7, 13, 16, 2, 19, 16, 10, 9, 9, 6, 10, 10, 16, 16 };
calc_combinations(bin_sizes);
char* sep = "";
for( unsigned i = 0; i < powers.size(); ++i ) {
if (powers[i]) {
std::cout << sep << i;
sep = " * ";
if (powers[i] > 1)
std::cout << "**" << powers[i];
}
}
std::cout << "\n\n";
}
The definition of N choose R is to compute the two products and divide one with the other,
(N * N-1 * N-2 * ... * N-R+1) / (1 * 2 * 3 * ... * R)
However, the multiplications may become too large really quick and overflow existing data type. The implementation trick is to reorder the multiplication and divisions as,
(N)/1 * (N-1)/2 * (N-2)/3 * ... * (N-R+1)/R
It's guaranteed that at each step the results is divisible (for n continuous numbers, one of them must be divisible by n, so is the product of these numbers).
For example, for N choose 3, at least one of the N, N-1, N-2 will be a multiple of 3, and for N choose 4, at least one of N, N-1, N-2, N-3 will be a multiple of 4.
C++ code given below.
int NCR(int n, int r)
{
if (r == 0) return 1;
/*
Extra computation saving for large R,
using property:
N choose R = N choose (N-R)
*/
if (r > n / 2) return NCR(n, n - r);
long res = 1;
for (int k = 1; k <= r; ++k)
{
res *= n - k + 1;
res /= k;
}
return res;
}
A nice way to implement n-choose-k is to base it not on factorial, but on a "rising product" function which is closely related to the factorial.
The rising_product(m, n) multiplies together m * (m + 1) * (m + 2) * ... * n, with rules for handling various corner cases, like n >= m, or n <= 1:
See here for an implementation nCk as well as nPk as a intrinsic functions in an interpreted programming language written in C:
static val rising_product(val m, val n)
{
val acc;
if (lt(n, one))
return one;
if (ge(m, n))
return one;
if (lt(m, one))
m = one;
acc = m;
m = plus(m, one);
while (le(m, n)) {
acc = mul(acc, m);
m = plus(m, one);
}
return acc;
}
val n_choose_k(val n, val k)
{
val top = rising_product(plus(minus(n, k), one), n);
val bottom = rising_product(one, k);
return trunc(top, bottom);
}
val n_perm_k(val n, val k)
{
return rising_product(plus(minus(n, k), one), n);
}
This code doesn't use operators like + and < because it is type generic (the type val represents a value of any kinds, such as various kinds of numbers including "bignum" integers) and because it is written in C (no overloading), and because it is the basis for a Lisp-like language that doesn't have infix syntax.
In spite of that, this n-choose-k implementation has a simple structure that is easy to follow.
Legend: le: less than or equal; ge: greater than or equal; trunc: truncating division; plus: addition, mul: multiplication, one: a val typed constant for the number one.
the line
else return (n*fact(n-1))/fact(n-1)*fact(n-r);
should be
else return (n*fact(n-1))/(fact(r)*fact(n-r));
or even
else return fact(n)/(fact(r)*fact(n-r));
Use double instead of int.
UPDATE:
Your formula is also wrong. You should use fact(n)/fact(r)/fact(n-r)
this is for reference to not to get time limit exceeded while solving nCr in competitive programming,i am posting this as it will be helpful to u as you already got answer for ur question,
Getting the prime factorization of the binomial coefficient is probably the most efficient way to calculate it, especially if multiplication is expensive. This is certainly true of the related problem of calculating factorial (see Click here for example).
Here is a simple algorithm based on the Sieve of Eratosthenes that calculates the prime factorization. The idea is basically to go through the primes as you find them using the sieve, but then also to calculate how many of their multiples fall in the ranges [1, k] and [n-k+1,n]. The Sieve is essentially an O(n \log \log n) algorithm, but there is no multiplication done. The actual number of multiplications necessary once the prime factorization is found is at worst O\left(\frac{n \log \log n}{\log n}\right) and there are probably faster ways than that.
prime_factors = []
n = 20
k = 10
composite = [True] * 2 + [False] * n
for p in xrange(n + 1):
if composite[p]:
continue
q = p
m = 1
total_prime_power = 0
prime_power = [0] * (n + 1)
while True:
prime_power[q] = prime_power[m] + 1
r = q
if q <= k:
total_prime_power -= prime_power[q]
if q > n - k:
total_prime_power += prime_power[q]
m += 1
q += p
if q > n:
break
composite[q] = True
prime_factors.append([p, total_prime_power])
print prime_factors
Recursive function is used incorrectly here. fact() function should be changed into this:
int fact(int n){
if(n==0||n==1) //factorial of both 0 and 1 is 1. Base case.
{
return 1;
}else
return (n*fact(n-1));//recursive call.
};
Recursive call should be made in else part.
NCR() function should be changed into this:
int NCR(int n,int r){
if(n==r) {
return 1;
} else if (r==0&&n!=0) {
return 1;
} else if(r==1)
{
return n;
}
else
{
return fact(n)/(fact(r)*fact(n-r));
}
};
// CPP program To calculate The Value Of nCr
#include <bits/stdc++.h>
using namespace std;
int fact(int n);
int nCr(int n, int r)
{
return fact(n) / (fact(r) * fact(n - r));
}
// Returns factorial of n
int fact(int n)
{
int res = 1;
for (int i = 2; i <= n; i++)
res = res * i;
return res;
}
// Driver code
int main()
{
int n = 5, r = 3;
cout << nCr(n, r);
return 0;
}