Number of ways to split N as sum of K numbers from the given range
Given four positive integer N, K, L, and R, the task is to split N as sum of K numbers lying in the range [L, R].
Note: Since the number of ways can be very large. Output answer modulo 1000000007.
Examples:
Input : N = 12, K = 3, L = 1, R = 5
Output : 10
{2, 5, 5}
{3, 4, 5}
{3, 5, 4}
{4, 3, 5}
{4, 4, 4}
{4, 5, 3}
{5, 2, 5}
{5, 3, 4}
{5, 4, 3}
{5, 5, 2}
Input : N = 23, K = 4, L = 2, R = 10
Output : 480
Naive Approach
We can solve the problem using recursion. At each step of recursion try to make a group of size L to R all
There will be two arguments in the recursion which changes:
- pos – the group number
- left – how much of N is left to be distributed
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
int calculate( int pos, int left,
int k, int L, int R)
{
if (pos == k) {
if (left == 0)
return 1;
else
return 0;
}
if (left == 0)
return 0;
int answer = 0;
for ( int i = L; i <= R; i++) {
if (i > left)
break ;
answer = (answer + calculate(pos + 1,
left - i, k, L, R))
% mod;
}
return answer;
}
int countWaystoDivide( int n, int k,
int L, int R)
{
return calculate(0, n, k, L, R);
}
int main()
{
int N = 12;
int K = 3;
int L = 1;
int R = 5;
cout << countWaystoDivide(N, K, L, R);
return 0;
}
|
Java
class GFG{
static int mod = 1000000007 ;
static int calculate( int pos, int left,
int k, int L, int R)
{
if (pos == k)
{
if (left == 0 )
return 1 ;
else
return 0 ;
}
if (left == 0 )
return 0 ;
int answer = 0 ;
for ( int i = L; i <= R; i++)
{
if (i > left)
break ;
answer = ((answer +
calculate(pos + 1 ,left - i,
k, L, R)) % mod);
}
return answer;
}
static int countWaystoDivide( int n, int k,
int L, int R)
{
return calculate( 0 , n, k, L, R);
}
public static void main(String[] args)
{
int N = 12 ;
int K = 3 ;
int L = 1 ;
int R = 5 ;
System.out.print(countWaystoDivide(N, K, L, R));
}
}
|
Python3
mod = 1000000007
def calculate(pos, left, k, L, R):
if (pos = = k):
if (left = = 0 ):
return 1
else :
return 0
if (left = = 0 ):
return 0
answer = 0
for i in range (L, R + 1 ):
if (i > left):
break
answer = (answer +
calculate(pos + 1 ,
left - i, k, L, R)) % mod
return answer
def countWaystoDivide(n, k, L, R):
return calculate( 0 , n, k, L, R)
N = 12
K = 3
L = 1
R = 5
print (countWaystoDivide(N, K, L, R))
|
C#
using System;
class GFG{
static int mod = 1000000007;
static int calculate( int pos, int left,
int k, int L, int R)
{
if (pos == k)
{
if (left == 0)
return 1;
else
return 0;
}
if (left == 0)
return 0;
int answer = 0;
for ( int i = L; i <= R; i++)
{
if (i > left)
break ;
answer = ((answer +
calculate(pos + 1,left - i,
k, L, R)) % mod);
}
return answer;
}
static int countWaystoDivide( int n, int k,
int L, int R)
{
return calculate(0, n, k, L, R);
}
public static void Main(String[] args)
{
int N = 12;
int K = 3;
int L = 1;
int R = 5;
Console.Write(countWaystoDivide(N, K, L, R));
}
}
|
Javascript
<script>
var mod = 1000000007;
function calculate(pos, left, k, L, R)
{
if (pos == k) {
if (left == 0)
return 1;
else
return 0;
}
if (left == 0)
return 0;
var answer = 0;
for ( var i = L; i <= R; i++) {
if (i > left)
break ;
answer = (answer + calculate(pos + 1,
left - i, k, L, R))
% mod;
}
return answer;
}
function countWaystoDivide(n, k, L, R)
{
return calculate(0, n, k, L, R);
}
var N = 12;
var K = 3;
var L = 1;
var R = 5;
document.write( countWaystoDivide(N, K, L, R));
</script>
|
Time Complexity: O(NK).
Efficient Approach: In the previous approach we can see that we are solving the subproblems repeatedly, i.e. it follows the property of Overlapping Subproblems. So we can memoize the same using DP table.
Below is the implementation of the above approach:
C++
#include <bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
int dp[1000][1000];
int calculate( int pos, int left,
int k, int L, int R)
{
if (pos == k) {
if (left == 0)
return 1;
else
return 0;
}
if (left == 0)
return 0;
if (dp[pos][left] != -1)
return dp[pos][left];
int answer = 0;
for ( int i = L; i <= R; i++) {
if (i > left)
break ;
answer = (answer + calculate(pos + 1,
left - i, k, L, R))
% mod;
}
return dp[pos][left] = answer;
}
int countWaystoDivide( int n, int k,
int L, int R)
{
memset (dp, -1, sizeof (dp));
return calculate(0, n, k, L, R);
}
int main()
{
int N = 12;
int K = 3;
int L = 1;
int R = 5;
cout << countWaystoDivide(N, K, L, R);
return 0;
}
|
Java
class GFG{
static int mod = 1000000007 ;
static int [][]dp = new int [ 1000 ][ 1000 ];
static int calculate( int pos, int left,
int k, int L, int R)
{
if (pos == k)
{
if (left == 0 )
return 1 ;
else
return 0 ;
}
if (left == 0 )
return 0 ;
if (dp[pos][left] != - 1 )
return dp[pos][left];
int answer = 0 ;
for ( int i = L; i <= R; i++)
{
if (i > left)
break ;
answer = (answer + calculate(pos + 1 , left - i,
k, L, R)) % mod;
}
return dp[pos][left] = answer;
}
static int countWaystoDivide( int n, int k,
int L, int R)
{
for ( int i = 0 ; i < 1000 ; i++)
{
for ( int j = 0 ; j < 1000 ; j++)
{
dp[i][j] = - 1 ;
}
}
return calculate( 0 , n, k, L, R);
}
public static void main(String[] args)
{
int N = 12 ;
int K = 3 ;
int L = 1 ;
int R = 5 ;
System.out.print(countWaystoDivide(N, K, L, R));
}
}
|
Python3
mod = 1000000007
dp = [[ - 1 for j in range ( 1000 )]
for i in range ( 1000 )]
def calculate(pos, left, k, L, R):
if (pos = = k):
if (left = = 0 ):
return 1
else :
return 0
if (left = = 0 ):
return 0
if (dp[pos][left] ! = - 1 ):
return dp[pos][left]
answer = 0
for i in range (L, R + 1 ):
if (i > left):
break
answer = (answer +
calculate(pos + 1 ,
left - i,
k, L, R)) % mod
dp[pos][left] = answer
return answer
def countWaystoDivide(n, k, L, R):
return calculate( 0 , n, k, L, R)
if __name__ = = "__main__" :
N = 12
K = 3
L = 1
R = 5
print (countWaystoDivide(N, K, L, R))
|
C#
using System;
class GFG{
static int mod = 1000000007;
static int [,]dp = new int [1000, 1000];
static int calculate( int pos, int left,
int k, int L, int R)
{
if (pos == k)
{
if (left == 0)
return 1;
else
return 0;
}
if (left == 0)
return 0;
if (dp[pos, left] != -1)
return dp[pos, left];
int answer = 0;
for ( int i = L; i <= R; i++)
{
if (i > left)
break ;
answer = (answer + calculate(pos + 1, left - i,
k, L, R)) % mod;
}
return dp[pos, left] = answer;
}
static int countWaystoDivide( int n, int k,
int L, int R)
{
for ( int i = 0; i < 1000; i++)
{
for ( int j = 0; j < 1000; j++)
{
dp[i, j] = -1;
}
}
return calculate(0, n, k, L, R);
}
public static void Main()
{
int N = 12;
int K = 3;
int L = 1;
int R = 5;
Console.Write(countWaystoDivide(N, K, L, R));
}
}
|
Javascript
<script>
var mod = 1000000007;
var dp = Array.from(Array(1000), ()=>Array(1000));
function calculate(pos, left, k, L, R)
{
if (pos == k) {
if (left == 0)
return 1;
else
return 0;
}
if (left == 0)
return 0;
if (dp[pos][left] != -1)
return dp[pos][left];
var answer = 0;
for ( var i = L; i <= R; i++) {
if (i > left)
break ;
answer = (answer + calculate(pos + 1,
left - i, k, L, R))
% mod;
}
return dp[pos][left] = answer;
}
function countWaystoDivide(n, k, L, R)
{
dp = Array.from(Array(1000), ()=>Array(1000).fill(-1));
return calculate(0, n, k, L, R);
}
var N = 12;
var K = 3;
var L = 1;
var R = 5;
document.write( countWaystoDivide(N, K, L, R));
</script>
|
Time Complexity: O(N*K).
Auxiliary Space: O(N*K).
Efficient approach : Using DP Tabulation method ( Iterative approach )
The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memorization(top-down) because memorization method needs extra stack space of recursion calls.
Steps to solve this problem :
- Create a vector to store the solution of the subproblems.
- Initialize the table with base cases
- Fill up the table iteratively
- Return the final solution
Implementation :
C++
#include <bits/stdc++.h>
using namespace std;
const int mod = 1000000007;
int dp[1000][1000];
int countWaystoDivide( int n, int k, int L, int R) {
memset (dp, 0, sizeof (dp));
dp[0][0] = 1;
for ( int i = 1; i <= k; i++) {
for ( int j = 0; j <= n; j++) {
for ( int l = L; l <= R; l++) {
if (l > j) break ;
dp[i][j] = (dp[i][j] + dp[i - 1][j - l]) % mod;
}
}
}
return dp[k][n];
}
int main() {
int N = 12;
int K = 3;
int L = 1;
int R = 5;
cout << countWaystoDivide(N, K, L, R);
return 0;
}
|
Java
import java.util.*;
public class Main {
static final int MOD = 1000000007 ;
public static int countWaystoDivide( int n, int k, int L, int R) {
int [][] dp = new int [k+ 1 ][n+ 1 ];
dp[ 0 ][ 0 ] = 1 ;
for ( int i = 1 ; i <= k; i++) {
for ( int j = 0 ; j <= n; j++) {
for ( int l = L; l <= R; l++) {
if (l > j) break ;
dp[i][j] = (dp[i][j] + dp[i - 1 ][j - l]) % MOD;
}
}
}
return dp[k][n];
}
public static void main(String[] args) {
int N = 12 ;
int K = 3 ;
int L = 1 ;
int R = 5 ;
System.out.println(countWaystoDivide(N, K, L, R));
}
}
|
Python3
mod = 1000000007
dp = []
def countWaystoDivide(n, k, L, R):
for i in range (k + 1 ):
dp.append([ 0 ] * (n + 1 ))
dp[ 0 ][ 0 ] = 1
for i in range ( 1 , k + 1 ):
for j in range (n + 1 ):
for l in range (L, R + 1 ):
if l > j:
break
dp[i][j] = (dp[i][j] + dp[i - 1 ][j - l]) % mod
return dp[k][n]
N = 12
K = 3
L = 1
R = 5
print (countWaystoDivide(N, K, L, R))
|
C#
using System;
public class GFG {
const int mod = 1000000007;
static int [, ] dp = new int [1000, 1000];
static int countWaystoDivide( int n, int k, int L, int R)
{
Array.Clear(dp, 0, dp.Length);
dp[0, 0] = 1;
for ( int i = 1; i <= k; i++) {
for ( int j = 0; j <= n; j++) {
for ( int l = L; l <= R; l++) {
if (l > j)
break ;
dp[i, j] = (dp[i, j] + dp[i - 1, j - l])
% mod;
}
}
}
return dp[k, n];
}
public static void Main()
{
int N = 12;
int K = 3;
int L = 1;
int R = 5;
Console.WriteLine(countWaystoDivide(N, K, L, R));
}
}
|
Javascript
const mod = 1000000007;
const dp = [];
function countWaystoDivide(n, k, L, R) {
for (let i = 0; i <= k; i++) {
dp[i] = [];
for (let j = 0; j <= n; j++) {
dp[i][j] = 0;
}
}
dp[0][0] = 1;
for (let i = 1; i <= k; i++) {
for (let j = 0; j <= n; j++) {
for (let l = L; l <= R; l++) {
if (l > j) break ;
dp[i][j] = (dp[i][j] + dp[i - 1][j - l]) % mod;
}
}
}
return dp[k][n];
}
const N = 12;
const K = 3;
const L = 1;
const R = 5;
console.log(countWaystoDivide(N, K, L, R));
|
Time Complexity: O(N*K).
Auxiliary Space: O(N*K).
Last Updated :
19 Apr, 2023
Like Article
Save Article
Share your thoughts in the comments
Please Login to comment...