Given two positive integers N and K, the task is to count the number of ways to write N as a sum of K non-negative integers.
Examples:
Input: N = 2, K = 3
Output: 6
Explanation:
The total ways in which 2 can be split into K non-negative integers are:
1. (0, 0, 2)
2. (0, 2, 0)
3. (2, 0, 0)
4. (0, 1, 1)
5. (1, 0, 1)
6. (1, 1, 0)Input: N = 3, K = 2
Output: 4
Explanation:
The total ways in which can be split 3 into 2 non-negative integers are:
1. (0, 3)
2. (3, 0)
3. (1, 2)
4. (2, 1)
Approach: This problem can be solved using Dynamic Programming. Below are the steps:
- Initialize a 2D array as dp[K+1][N+1] where rows correspond to the number of the element we pick and columns correspond to the corresponding sum.
- Start filling the first row and column with taking sum as K in the above table dp[][].
- Suppose we reach at ith row and jth column, i.e i elements we can pick and we need to get sum j. To calculate the number of ways till dp[i][j] choose first (i – 1) elements and next (j – x) where x is the sum of first (i – 1) elements.
- Repeat the above steps to fill the dp[][] array.
- The value dp[n][m] will give the required result.
Below is the implementation of the above approach:
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Function to count the number of ways // to write N as sum of k non-negative // integers int countWays( int n, int m)
{ // Initialise dp[][] array
int dp[m + 1][n + 1];
// Only 1 way to choose the value
// with sum K
for ( int i = 0; i <= n; i++) {
dp[1][i] = 1;
}
// Initialise sum
int sum;
for ( int i = 2; i <= m; i++) {
for ( int j = 0; j <= n; j++) {
sum = 0;
// Count the ways from previous
// states
for ( int k = 0; k <= j; k++) {
sum += dp[i - 1][k];
}
// Update the sum
dp[i][j] = sum;
}
}
// Return the final count of ways
return dp[m][n];
} // Driver Code int main()
{ int N = 2, K = 3;
// Function call
cout << countWays(N, K);
return 0;
} |
// Java program for the above approach import java.util.*;
class GFG{
// Function to count the number of ways // to write N as sum of k non-negative // integers static int countWays( int n, int m)
{ // Initialise dp[][] array
int [][]dp = new int [m + 1 ][n + 1 ];
// Only 1 way to choose the value
// with sum K
for ( int i = 0 ; i <= n; i++)
{
dp[ 1 ][i] = 1 ;
}
// Initialise sum
int sum;
for ( int i = 2 ; i <= m; i++)
{
for ( int j = 0 ; j <= n; j++)
{
sum = 0 ;
// Count the ways from previous
// states
for ( int k = 0 ; k <= j; k++)
{
sum += dp[i - 1 ][k];
}
// Update the sum
dp[i][j] = sum;
}
}
// Return the final count of ways
return dp[m][n];
} // Driver Code public static void main(String[] args)
{ int N = 2 , K = 3 ;
// Function call
System.out.print(countWays(N, K));
} } // This code is contributed by gauravrajput1 |
# Python3 program for the above approach # Function to count the number of ways # to write N as sum of k non-negative # integers def countWays(n, m):
# Initialise dp[][] array
dp = [[ 0 for i in range (n + 1 )]
for i in range (m + 1 )]
# Only 1 way to choose the value
# with sum K
for i in range (n + 1 ):
dp[ 1 ][i] = 1
# Initialise sum
sum = 0
for i in range ( 2 , m + 1 ):
for j in range (n + 1 ):
sum = 0
# Count the ways from previous
# states
for k in range (j + 1 ):
sum + = dp[i - 1 ][k]
# Update the sum
dp[i][j] = sum
# Return the final count of ways
return dp[m][n]
# Driver Code if __name__ = = '__main__' :
N = 2
K = 3
# Function call
print (countWays(N, K))
# This code is contributed by Mohit Kumar |
// C# program for the above approach using System;
class GFG{
// Function to count the number of ways // to write N as sum of k non-negative // integers static int countWays( int n, int m)
{ // Initialise [,]dp array
int [,]dp = new int [m + 1, n + 1];
// Only 1 way to choose the value
// with sum K
for ( int i = 0; i <= n; i++)
{
dp[1, i] = 1;
}
// Initialise sum
int sum;
for ( int i = 2; i <= m; i++)
{
for ( int j = 0; j <= n; j++)
{
sum = 0;
// Count the ways from previous
// states
for ( int k = 0; k <= j; k++)
{
sum += dp[i - 1, k];
}
// Update the sum
dp[i, j] = sum;
}
}
// Return the readonly count of ways
return dp[m, n];
} // Driver Code public static void Main(String[] args)
{ int N = 2, K = 3;
// Function call
Console.Write(countWays(N, K));
} } // This code is contributed by gauravrajput1 |
<script> // Javascript program for the above approach // Function to count the number of ways // to write N as sum of k non-negative // integers function countWays(n, m)
{ // Initialise dp[][] array
var dp = Array.from(Array(m+1), ()=>Array(n+1));
// Only 1 way to choose the value
// with sum K
for ( var i = 0; i <= n; i++) {
dp[1][i] = 1;
}
// Initialise sum
var sum;
for ( var i = 2; i <= m; i++) {
for ( var j = 0; j <= n; j++) {
sum = 0;
// Count the ways from previous
// states
for ( var k = 0; k <= j; k++) {
sum += dp[i - 1][k];
}
// Update the sum
dp[i][j] = sum;
}
}
// Return the final count of ways
return dp[m][n];
} // Driver Code var N = 2, K = 3;
// Function call document.write( countWays(N, K)); </script> |
6
Time Complexity: O(K*N2)
Auxiliary Space Complexity: O(N*K)
Optimized Approach: The idea of calculating the sum and then storing the count increases the time complexity. We can decrease it by storing the sum in the above dp[][] table.
Below is the implementation of the above approach:
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Function to count the number of ways // to write N as sum of k non-negative // integers int countWays( int n, int m)
{ // Initialise dp[][] array
int dp[m + 1][n + 1];
// Fill the dp[][] with sum = m
for ( int i = 0; i <= n; i++) {
dp[1][i] = 1;
if (i != 0) {
dp[1][i] += dp[1][i - 1];
}
}
// Iterate the dp[][] to fill the
// dp[][] array
for ( int i = 2; i <= m; i++) {
for ( int j = 0; j <= n; j++) {
// Condition for first column
if (j == 0) {
dp[i][j] = dp[i - 1][j];
}
// Else fill the dp[][] with
// sum till (i, j)
else {
dp[i][j] = dp[i - 1][j];
// If reach the end, then
// return the value
if (i == m && j == n) {
return dp[i][j];
}
// Update at current index
dp[i][j] += dp[i][j - 1];
}
}
}
} // Driver Code int main()
{ int N = 2, K = 3;
// Function call
cout << countWays(N, K);
return 0;
} |
// Java program for the above approach import java.util.*;
class GFG{
// Function to count the number of ways // to write N as sum of k non-negative // integers static int countWays( int n, int m)
{ // Initialise dp[][] array
int [][]dp = new int [m + 1 ][n + 1 ];
// Fill the dp[][] with sum = m
for ( int i = 0 ; i <= n; i++)
{
dp[ 1 ][i] = 1 ;
if (i != 0 )
{
dp[ 1 ][i] += dp[ 1 ][i - 1 ];
}
}
// Iterate the dp[][] to fill the
// dp[][] array
for ( int i = 2 ; i <= m; i++)
{
for ( int j = 0 ; j <= n; j++)
{
// Condition for first column
if (j == 0 )
{
dp[i][j] = dp[i - 1 ][j];
}
// Else fill the dp[][] with
// sum till (i, j)
else
{
dp[i][j] = dp[i - 1 ][j];
// If reach the end, then
// return the value
if (i == m && j == n)
{
return dp[i][j];
}
// Update at current index
dp[i][j] += dp[i][j - 1 ];
}
}
}
return Integer.MIN_VALUE;
} // Driver Code public static void main(String[] args)
{ int N = 2 , K = 3 ;
// Function call
System.out.print(countWays(N, K));
} } // This code is contributed by sapnasingh4991 |
# Python3 program for the above approach # Function to count the number of ways # to write N as sum of k non-negative # integers def countWays(n, m):
# Initialise dp[][] array
dp = [[ 0 for i in range (n + 1 )]
for j in range (m + 1 )]
# Fill the dp[][] with sum = m
for i in range (n + 1 ):
dp[ 1 ][i] = 1
if (i ! = 0 ):
dp[ 1 ][i] + = dp[ 1 ][i - 1 ]
# Iterate the dp[][] to fill the
# dp[][] array
for i in range ( 2 , m + 1 ):
for j in range (n + 1 ):
# Condition for first column
if (j = = 0 ):
dp[i][j] = dp[i - 1 ][j]
# Else fill the dp[][] with
# sum till (i, j)
else :
dp[i][j] = dp[i - 1 ][j]
# If reach the end, then
# return the value
if (i = = m and j = = n):
return dp[i][j]
# Update at current index
dp[i][j] + = dp[i][j - 1 ]
# Driver Code N = 2
K = 3
# Function call print (countWays(N, K))
# This code is contributed by ShubhamCoder |
// C# program for the above approach using System;
class GFG{
// Function to count the number of ways // to write N as sum of k non-negative // integers static int countWays( int n, int m)
{ // Initialise dp[][] array
int [,]dp = new int [m + 1, n + 1];
// Fill the dp[][] with sum = m
for ( int i = 0; i <= n; i++)
{
dp[1, i] = 1;
if (i != 0)
{
dp[1, i] += dp[1, i - 1];
}
}
// Iterate the dp[][] to fill the
// dp[][] array
for ( int i = 2; i <= m; i++)
{
for ( int j = 0; j <= n; j++)
{
// Condition for first column
if (j == 0)
{
dp[i, j] = dp[i - 1, j];
}
// Else fill the dp[][] with
// sum till (i, j)
else
{
dp[i, j] = dp[i - 1, j];
// If reach the end, then
// return the value
if (i == m && j == n)
{
return dp[i, j];
}
// Update at current index
dp[i, j] += dp[i, j - 1];
}
}
}
return Int32.MinValue;
} // Driver Code public static void Main()
{ int N = 2, K = 3;
// Function call
Console.Write(countWays(N, K));
} } // This code is contributed by Code_Mech |
<script> // JavaScript program for the above approach // Function to count the number of ways // to write N as sum of k non-negative // integers function countWays(n,m)
{ // Initialise dp[][] array
let dp = new Array(m + 1);
for (let i=0;i<m+1;i++)
{
dp[i]= new Array(n+1);
for (let j=0;j<n+1;j++)
dp[i][j]=0;
}
// Fill the dp[][] with sum = m
for (let i = 0; i <= n; i++)
{
dp[1][i] = 1;
if (i != 0)
{
dp[1][i] += dp[1][i - 1];
}
}
// Iterate the dp[][] to fill the
// dp[][] array
for (let i = 2; i <= m; i++)
{
for (let j = 0; j <= n; j++)
{
// Condition for first column
if (j == 0)
{
dp[i][j] = dp[i - 1][j];
}
// Else fill the dp[][] with
// sum till (i, j)
else
{
dp[i][j] = dp[i - 1][j];
// If reach the end, then
// return the value
if (i == m && j == n)
{
return dp[i][j];
}
// Update at current index
dp[i][j] += dp[i][j - 1];
}
}
}
return Number.MIN_VALUE;
} // Driver Code let N = 2, K = 3; // Function call document.write(countWays(N, K)); // This code is contributed by patel2127 </script> |
6
Time Complexity: O(K*N)
Auxiliary Space: O(N*K)
Efficient Approach : using array instead of 2d matrix to optimize space complexity
In previous code we can se that dp[i][j] is dependent upon dp[i-1][j] or dp[i][j-1] so we can assume that dp[i-1] is previous row and dp[i] is current row.
Implementations Steps :
- Create two vectors prev and curr each of size n+1, where n is a given number.
- Initialize them with base cases.
- Now In previous code change dp[i] to curr and change dp[i-1] to prev to keep track only of the two main rows.
- After every iteration update previous row to current row to iterate further.
Implementation :
// C++ program for the above approach #include <bits/stdc++.h> using namespace std;
// Function to count the number of ways // to write N as sum of k non-negative // integers int countWays( int n, int m)
{ // initialize 2 vectors determining 2 rows of DP
vector< int >prev(n+1 , 0);
vector< int >curr(n+1 , 0);
// Base case initialize the prev vector
for ( int i = 0; i <= n; i++) {
prev[i] = 1;
if (i != 0) {
prev[i] += prev[i - 1];
}
}
// fill curr vector by the help of prev vector
for ( int i = 2; i <= m; i++) {
for ( int j = 0; j <= n; j++) {
// Condition for first column
if (j == 0) {
curr[j] = prev[j];
}
// Else fill the curr with
// sum till (i, j)
else {
curr[j] = prev[j];
// If reach the end, then
// return the value
if (i == m && j == n) {
return curr[j];
}
// Update at current index
curr[j] += curr[j - 1];
}
}
prev = curr;
}
} // Driver Code int main()
{ int N = 2, K = 3;
// Function call
cout << countWays(N, K);
return 0;
} |
import java.util.*;
public class Main {
// Function to count the number of ways
// to write N as sum of k non-negative
// integers
static int countWays( int n, int m) {
// initialize 2 vectors determining 2 rows of DP
int [] prev = new int [n + 1 ];
int [] curr = new int [n + 1 ];
// Base case initialize the prev vector
for ( int i = 0 ; i <= n; i++) {
prev[i] = 1 ;
if (i != 0 ) {
prev[i] += prev[i - 1 ];
}
}
// fill curr vector by the help of prev vector
for ( int i = 2 ; i <= m; i++) {
for ( int j = 0 ; j <= n; j++) {
// Condition for first column
if (j == 0 ) {
curr[j] = prev[j];
}
// Else fill the curr with
// sum till (i, j)
else {
curr[j] = prev[j];
// If reach the end, then
// return the value
if (i == m && j == n) {
return curr[j];
}
// Update at current index
curr[j] += curr[j - 1 ];
}
}
// Update prev array
prev = curr.clone();
}
return curr[n];
}
// Driver Code
public static void main(String[] args) {
int N = 2 , K = 3 ;
// Function call
System.out.println(countWays(N, K));
}
} |
# Define a function to count the number of ways to write N as sum of K non-negative integers def countWays(n, m):
# initialize 2 lists determining 2 rows of DP
prev = [ 0 ] * (n + 1 )
curr = [ 0 ] * (n + 1 )
# Base case initialize the prev list
for i in range (n + 1 ):
prev[i] = 1
if i ! = 0 :
prev[i] + = prev[i - 1 ]
# fill curr list by the help of prev list
for i in range ( 2 , m + 1 ):
for j in range (n + 1 ):
# Condition for first column
if j = = 0 :
curr[j] = prev[j]
# Else fill the curr with sum till (i, j)
else :
curr[j] = prev[j]
# If reach the end, then return the value
if i = = m and j = = n:
return curr[j]
# Update at current index
curr[j] + = curr[j - 1 ]
prev = curr.copy()
# Driver Code N = 2
K = 3
# Function call print (countWays(N, K))
|
using System;
class GFG
{ // Function to count the number of ways
// to write N as sum of k non-negative
// integers
static int countWays( int n, int m)
{
// Initialize 2 vectors determining 2 rows of DP
int [] prev = new int [n + 1];
int [] curr = new int [n + 1];
// Base case initialize the prev vector
for ( int i = 0; i <= n; i++)
{
prev[i] = 1;
if (i != 0)
{
prev[i] += prev[i - 1];
}
}
// Fill curr vector by the help of prev vector
for ( int i = 2; i <= m; i++)
{
for ( int j = 0; j <= n; j++)
{
// Condition for first column
if (j == 0)
{
curr[j] = prev[j];
}
// Else fill the curr with
// sum till (i, j)
else
{
curr[j] = prev[j];
// If reach the end, then
// return the value
if (i == m && j == n)
{
return curr[j];
}
// Update at current index
curr[j] += curr[j - 1];
}
}
prev = curr;
}
return curr[n];
}
// Driver Code
static void Main()
{
int N = 2, K = 3;
// Function call
Console.WriteLine(countWays(N, K));
}
} |
// Function to count the number of ways // to write N as sum of k non-negative // integers function countWays(n, m) {
// initialize 2 arrays determining 2 rows of DP
let prev = new Array(n + 1).fill(0);
let curr = new Array(n + 1).fill(0);
// Base case initialize the prev array
for (let i = 0; i <= n; i++) {
prev[i] = 1;
if (i != 0) {
prev[i] += prev[i - 1];
}
}
// fill curr array by the help of prev array
for (let i = 2; i <= m; i++) {
for (let j = 0; j <= n; j++) {
// Condition for first column
if (j == 0) {
curr[j] = prev[j];
}
// Else fill the curr with
// sum till (i, j)
else {
curr[j] = prev[j];
// If reach the end, then
// return the value
if (i == m && j == n) {
return curr[j];
}
// Update at current index
curr[j] += curr[j - 1];
}
}
prev = [...curr];
}
} // Driver Code let N = 2, K = 3;
// Function call console.log(countWays(N, K)); |
6
Time Complexity: O(K*N)
Auxiliary Space: O(N)