Count the number of ways to divide N in k groups incrementally - GeeksforGeeks

26 Nov, 2021
Given two integers N and K, the task is to count the number of ways to divide N into K groups of positive integers such that their sum is N and the number of elements in groups follows a non-decreasing order (i.e group[i] <= group[i+1]).Examples:  
Input: N = 8, K = 4 Output: 5 Explanation: Their are 5 groups such that their sum is 8 and the number of positive integers in each group is 4. [1, 1, 1, 5], [1, 1, 2, 4], [1, 1, 3, 3], [1, 2, 2, 3], [2, 2, 2, 2]Input: N = 24, K = 5 Output: 164 Explanation: There are 164 such groups such that their sum is 24 and number of positive integers in each group is 5
Different Approaches:1. Naive Approach (Time: O(NK), Space: O(N))2. Memoization  (Time: O((N3*K), Space: O(N2*K))3. Bottom-Up Dynamic Programming (Time: O(N*K), Space: O(N*K))
Naive Approach: We can solve this problem using recursion. At each step of recursion put all the values greater than equal to the previously computed value.Below is the implementation of the above approach: 
C++
Java
Python3
C#
Javascript
// C++ implementation to count the// number of ways to divide N in// groups such that each group// has K number of elements #include <bits/stdc++.h> using namespace std; // Function to count the number// of ways to divide the number N// in groups such that each group// has K number of elementsint calculate(int pos, int prev,                 int left, int k){    // Base Case    if (pos == k) {        if (left == 0)            return 1;        else            return 0;    }     // if N is divides completely    // into less than k groups    if (left == 0)        return 0;     int answer = 0;         // put all possible values    // greater equal to prev    for (int i = prev; i <= left; i++) {        answer += calculate(pos + 1, i,                          left - i, k);    }    return answer;} // Function to count the number of// ways to divide the number Nint countWaystoDivide(int n, int k){    return calculate(0, 1, n, k);} // Driver Codeint main(){    int N = 8;    int K = 4;     cout << countWaystoDivide(N, K);    return 0;}
// Java implementation to count the// number of ways to divide N in// groups such that each group// has K number of elementsimport java.util.*;class GFG{ // Function to count the number// of ways to divide the number N// in groups such that each group// has K number of elementsstatic int calculate(int pos, int prev,                     int left, int k){         // Base Case    if (pos == k)    {        if (left == 0)            return 1;        else            return 0;    }     // If N is divides completely    // into less than k groups    if (left == 0)        return 0;     int answer = 0;         // Put all possible values    // greater equal to prev    for(int i = prev; i <= left; i++)    {       answer += calculate(pos + 1, i,                           left - i, k);    }    return answer;} // Function to count the number of// ways to divide the number Nstatic int countWaystoDivide(int n, int k){    return calculate(0, 1, n, k);} // Driver Codepublic static void main(String[] args){    int N = 8;    int K = 4;     System.out.print(countWaystoDivide(N, K));}} // This code is contributed by Rajput-Ji
# Python3 implementation to count the# number of ways to divide N in# groups such that each group# has K number of elements # Function to count the number# of ways to divide the number N# in groups such that each group# has K number of elementsdef calculate(pos, prev, left, k):         # Base Case    if (pos == k):        if (left == 0):            return 1;        else:            return 0;     # If N is divides completely    # into less than k groups    if (left == 0):        return 0;     answer = 0;     # Put all possible values    # greater equal to prev    for i in range(prev, left + 1):        answer += calculate(pos + 1, i,                           left - i, k);     return answer; # Function to count the number of# ways to divide the number Ndef countWaystoDivide(n, k):         return calculate(0, 1, n, k); # Driver Codeif __name__ == '__main__':         N = 8;    K = 4;     print(countWaystoDivide(N, K)); # This code is contributed by 29AjayKumar
// C# implementation to count the// number of ways to divide N in// groups such that each group// has K number of elementsusing System; class GFG{ // Function to count the number// of ways to divide the number N// in groups such that each group// has K number of elementsstatic int calculate(int pos, int prev,                     int left, int k){         // Base Case    if (pos == k)    {        if (left == 0)            return 1;        else            return 0;    }     // If N is divides completely    // into less than k groups    if (left == 0)        return 0;     int answer = 0;         // Put all possible values    // greater equal to prev    for(int i = prev; i <= left; i++)    {       answer += calculate(pos + 1, i,                           left - i, k);    }    return answer;} // Function to count the number of// ways to divide the number Nstatic int countWaystoDivide(int n, int k){    return calculate(0, 1, n, k);} // Driver Codepublic static void Main(String[] args){    int N = 8;    int K = 4;     Console.Write(countWaystoDivide(N, K));}} // This code is contributed by Rajput-Ji
<script> // Javascript implementation to count the// number of ways to divide N in// groups such that each group// has K number of elements   // Function to count the number// of ways to divide the number N// in groups such that each group// has K number of elementsfunction calculate(pos, prev,                left, k){    // Base Case    if (pos == k) {        if (left == 0)            return 1;        else            return 0;    }     // if N is divides completely    // into less than k groups    if (left == 0)        return 0;     let answer = 0;         // put all possible values    // greater equal to prev    for (let i = prev; i <= left; i++) {        answer += calculate(pos + 1, i,                        left - i, k);    }    return answer;} // Function to count the number of// ways to divide the number Nfunction countWaystoDivide(n, k){    return calculate(0, 1, n, k);} // Driver Code     let N = 8;    let K = 4;     document.write(countWaystoDivide(N, K));     // This code is contributed by Mayank Tyagi     </script>
5
Time complexity: O(NK)Auxiliary Space: O(N).Memoization 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 the DP table.Below is the implementation of the above approach:
C++
Java
Python3
C#
Javascript
// C++ implementation to count the// number of ways to divide N in// groups such that each group// has K number of elements #include <bits/stdc++.h> using namespace std; // DP Tableint dp[100][100][100]; // Function to count the number// of ways to divide the number N// in groups such that each group// has K number of elementsint calculate(int pos, int prev,                int left, int k){    // Base Case    if (pos == k) {        if (left == 0)            return 1;        else            return 0;    }    // if N is divides completely    // into less than k groups    if (left == 0)        return 0;     // If the subproblem has been    // solved, use the value    if (dp[pos][prev][left] != -1)        return dp[pos][prev][left];     int answer = 0;    // put all possible values    // greater equal to prev    for (int i = prev; i <= left; i++) {        answer += calculate(pos + 1, i,                           left - i, k);    }     return dp[pos][prev][left] = answer;} // Function to count the number of// ways to divide the number N in groupsint countWaystoDivide(int n, int k){    // Initialize DP Table as -1    memset(dp, -1, sizeof(dp));     return calculate(0, 1, n, k);} // Driver Codeint main(){    int N = 8;    int K = 4;     cout << countWaystoDivide(N, K);    return 0;}
// Java implementation to count the// number of ways to divide N in// groups such that each group// has K number of elementsimport java.util.*;class GFG{  // DP Tablestatic int [][][]dp = new int[100][100][100];  // Function to count the number// of ways to divide the number N// in groups such that each group// has K number of elementsstatic int calculate(int pos, int prev,                     int left, int k){    // Base Case    if (pos == k)    {        if (left == 0)            return 1;        else            return 0;    }       // if N is divides completely    // into less than k groups    if (left == 0)        return 0;      // If the subproblem has been    // solved, use the value    if (dp[pos][prev][left] != -1)        return dp[pos][prev][left];      int answer = 0;       // put all possible values    // greater equal to prev    for (int i = prev; i <= left; i++)    {        answer += calculate(pos + 1, i,                           left - i, k);    }      return dp[pos][prev][left] = answer;}  // Function to count the number of// ways to divide the number N in groupsstatic int countWaystoDivide(int n, int k){    // Initialize DP Table as -1        for (int i = 0; i < 100; i++)        {            for (int j = 0; j < 100; j++)            {                for (int l = 0; l < 100; l++)                    dp[i][j][l] = -1;            }        }      return calculate(0, 1, n, k);}  // Driver Codepublic static void main(String[] args){    int N = 8;    int K = 4;      System.out.print(countWaystoDivide(N, K));}} // This code is contributed by Rajput-Ji
# Python3 implementation to count the# number of ways to divide N in# groups such that each group# has K number of elements  # DP Tabledp = [[[0 for i in range(50)]             for j in range(50)]          for j in range(50)] # Function to count the number# of ways to divide the number N# in groups such that each group# has K number of elementsdef calculate(pos, prev, left, k):        # Base Case    if (pos == k):        if (left == 0):            return 1;        else:            return 0;      # if N is divides completely    # into less than k groups    if (left == 0):        return 0;      # If the subproblem has been    # solved, use the value    if (dp[pos][prev][left] != -1):        return dp[pos][prev][left];      answer = 0;      # put all possible values    # greater equal to prev    for i in range(prev,left+1):        answer += calculate(pos + 1, i,                            left - i, k);    dp[pos][prev][left] = answer;    return dp[pos][prev][left];  # Function to count the number of# ways to divide the number N in groupsdef countWaystoDivide(n, k):       # Initialize DP Table as -1    for i in range(50):        for j in range(50):            for l in range(50):                dp[i][j][l] = -1;      return calculate(0, 1, n, k);  # Driver Codeif __name__ == '__main__':    N = 8;    K = 4;      print(countWaystoDivide(N, K));  # This code is contributed by Rajput-Ji
// C# implementation to count the// number of ways to divide N in// groups such that each group// has K number of elementsusing System;class GFG{  // DP Tablestatic int [,,]dp = new int[50, 50, 50];  // Function to count the number// of ways to divide the number N// in groups such that each group// has K number of elementsstatic int calculate(int pos, int prev,                     int left, int k){    // Base Case    if (pos == k)    {        if (left == 0)            return 1;        else            return 0;    }       // if N is divides completely    // into less than k groups    if (left == 0)        return 0;      // If the subproblem has been    // solved, use the value    if (dp[pos, prev, left] != -1)        return dp[pos, prev, left];      int answer = 0;       // put all possible values    // greater equal to prev    for (int i = prev; i <= left; i++)    {        answer += calculate(pos + 1, i,                           left - i, k);    }      return dp[pos, prev, left] = answer;}  // Function to count the number of// ways to divide the number N in groupsstatic int countWaystoDivide(int n, int k){    // Initialize DP Table as -1        for (int i = 0; i < 50; i++)        {            for (int j = 0; j < 50; j++)            {                for (int l = 0; l < 50; l++)                    dp[i, j, l] = -1;            }        }      return calculate(0, 1, n, k);}  // Driver Codepublic static void Main(String[] args){    int N = 8;    int K = 4;      Console.Write(countWaystoDivide(N, K));}} // This code is contributed by gauravrajput1
<script> // JavaScript implementation to count the// number of ways to divide N in// groups such that each group// has K number of elements // DP Tablelet dp = new Array(500);for(let i=0;i<500;i++){    dp[i]=new Array(500);    for(let j=0;j<500;j++)    {        dp[i][j]=new Array(500);        for(let k=0;k<500;k++)            dp[i][j][k]=0;    }} // Function to count the number// of ways to divide the number N// in groups such that each group// has K number of elementsfunction calculate(pos,prev,left,k){    // Base Case    if (pos == k)    {        if (left == 0)            return 1;        else            return 0;    }        // if N is divides completely    // into less than k groups    if (left == 0)        return 0;       // If the subproblem has been    // solved, use the value    if (dp[pos][prev][left] != -1)        return dp[pos][prev][left];       let answer = 0;        // put all possible values    // greater equal to prev    for (let i = prev; i <= left; i++)    {        answer += calculate(pos + 1, i,                           left - i, k);    }       return dp[pos][prev][left] = answer;} // Function to count the number of// ways to divide the number N in groupsfunction countWaystoDivide(n,k){    // Initialize DP Table as -1        for (let i = 0; i < 500; i++)        {            for (let j = 0; j < 500; j++)            {                for (let l = 0; l < 500; l++)                    dp[i][j][l] = -1;            }        }       return calculate(0, 1, n, k);} // Driver Codelet N = 8;let K = 4; document.write(countWaystoDivide(N, K));  // This code is contributed by unknown2108 </script>
Output:
5
Time complexity: O(N^3 * K) Auxiliary Space: O(N^2 * K).
Bottom-Up DP:  We are asked to find CountWaystoDivide(n,k) So the recurrence approach and explanation of DP is:
CountWaystoDivide( n , k ) = CountWaystoDivide( n-k , k ) + CountWaystoDivide( n-1 , k-1 ) 
Explanation:Divide CountWaystoDivide( n , k ) into two parts where
If first element is 1 then the rest form a total  of n-1 divide into k-1 so CountWaystoDivide( n-1 , k-1 )If first element is greater than 1 then, we can subtract 1 from every element and get a valid partition of n-k into k parts, hence CountWaystoDivide( n-1 , k-1 ).
If first element is 1 then the rest form a total  of n-1 divide into k-1 so CountWaystoDivide( n-1 , k-1 )
If first element is greater than 1 then, we can subtract 1 from every element and get a valid partition of n-k into k parts, hence CountWaystoDivide( n-1 , k-1 ).
Mathematical Explanation of DP:
As each group must have at least one person, so, give each group one person, then we are left with n-k persons, which can we divided into 1,2,3..or k groups. Thus our dp will be: dp[n][k] = dp[n-k][1] + dp[n-k][2] + dp[n-k][3] + .... + dp[n-k][k].At first look, the previous might give O(N3) vibes, but with a little manipulation we can optimize it: dp[n][k] = dp[(n-1)-(k-1)][1] + dp[(n-1)-(k-1)][2] + ... + dp[(n-1)-(k-1)][k-1] + dp[(n-1)-(k-1)][k]From the recurrence, we can write:dp[n][k] = dp[n-1][k-1] + dp[n-k][k]
As each group must have at least one person, so, give each group one person, then we are left with n-k persons, which can we divided into 1,2,3..or k groups. Thus our dp will be: dp[n][k] = dp[n-k][1] + dp[n-k][2] + dp[n-k][3] + .... + dp[n-k][k].
At first look, the previous might give O(N3) vibes, but with a little manipulation we can optimize it: dp[n][k] = dp[(n-1)-(k-1)][1] + dp[(n-1)-(k-1)][2] + ... + dp[(n-1)-(k-1)][k-1] + dp[(n-1)-(k-1)][k]From the recurrence, we can write:dp[n][k] = dp[n-1][k-1] + dp[n-k][k]
Steps to solve the problem using DP:
Initialize a 2-D array dp[][] of size n+1, k+1 where dp[i][j] will store the optimal solution to divide n into k groups.
For each value from i=0 to n, dp[n][1] will be 1 since total ways to divide n into 1 is 1. also dp[0][0] will be 1.
      DP states are updated as follows:
If i>=j then dp[i][j] = dp[i-1][j-1] + dp[i-j][j]
otherwise i-j<0 and dp[i-j][j] become zero so dp[i][j] = dp[i-1][j-1] 
C++
Java
Python3
C#
Javascript
// C++ implementation to count the// number of ways to divide N in// groups such that each group// has K number of elements #include <bits/stdc++.h> using namespace std; // Function to count the number of// ways to divide the number N in groupsint countWaystoDivide(int n, int k){    if (n < k)        return 0; // When n is less than k, No way to divide                  // into groups    vector<vector<int> > dp(n + 1, vector<int>(k + 1));     for (int i = 1; i <= n; i++)        dp[i][1]            = 1; // exact one way to divide n to 1 group    dp[0][0] = 1;     for (int i = 1; i <= n; i++) {        for (int j = 2; j <= k; j++) {            if (i >= j)                dp[i][j] = dp[i - j][j] + dp[i - 1][j - 1];            else                dp[i][j]                    = dp[i - 1][j - 1]; // i<j so dp[i-j][j]                                        // becomes zero        }    }    return dp[n][k]; // returning number of ways to divide N                     // in k groups} // Driver Codeint main(){    int N = 8;    int K = 4;     cout << countWaystoDivide(N, K);    return 0;}
// Java implementation to count the// number of ways to divide N in// groups such that each group// has K number of elementsimport java.io.*; class GFG {   static int countWaystoDivide(int n, int k)  {    if (n < k)      return 0; // When n is less than k, No way to divide    // into groups     int [][]dp = new int[n+1][k+1];    for (int i = 1; i <= n; i++)      dp[i][1]      = 1; // exact one way to divide n to 1 group    dp[0][0] = 1;     for (int i = 1; i <= n; i++) {      for (int j = 2; j <= k; j++) {        if (i >= j)          dp[i][j] = dp[i - j][j] + dp[i - 1][j - 1];        else          dp[i][j]          = dp[i - 1][j - 1]; // i<j so dp[i-j][j]        // becomes zero      }    }    return dp[n][k]; // returning number of ways to divide N    // in k groups  }   // Driver code  public static void main (String[] args)  {    int N = 8;    int K = 4;     System.out.println(countWaystoDivide(N, K));  }} // This code is contributed by rohitsingh07052.
# Python3 implementation to count the# number of ways to divide N in# groups such that each group# has K number of elements # DP Table# Function to count the number of# ways to divide the number N in groups  def countWaystoDivide(n, k):    if(n < k):        return 0     dp = [[0 for i in range(k+1)] for i in range(n+1)]    for i in range(1, n+1):        dp[i][1] = 1    dp[0][0] = 1    for i in range(1, n+1):        for j in range(2, k+1):            if(i >= j):                dp[i][j] = dp[i-1][j-1] + dp[i-j][j]             else:                dp[i][j] = dp[i-1][j-1]    return dp[n][k]  # Driver Codeif __name__ == '__main__':    N = 8    K = 4     print(countWaystoDivide(N, K)) # This code is contributed by Rajput-Ji
// C# implementation to count the// number of ways to divide N in// groups such that each group// has K number of elementsusing System;using System.Collections.Generic;class GFG {       static int countWaystoDivide(int n, int k)  {    if (n < k)      return 0; // When n is less than k, No way to divide    // into groups      int[,] dp = new int[n + 1, k + 1];    for (int i = 1; i <= n; i++)      dp[i, 1] = 1; // exact one way to divide n to 1 group    dp[0, 0] = 1;      for (int i = 1; i <= n; i++) {      for (int j = 2; j <= k; j++) {        if (i >= j)          dp[i,j] = dp[i - j,j] + dp[i - 1,j - 1];        else          dp[i,j] = dp[i - 1, j - 1]; // i<j so dp[i-j][j]        // becomes zero      }    }    return dp[n,k]; // returning number of ways to divide N    // in k groups  }     static void Main() {    int N = 8;    int K = 4;      Console.Write(countWaystoDivide(N, K));  }} // This code is contributed by rameshtravel07.
<script>    // Javascript implementation to count the    // number of ways to divide N in    // groups such that each group    // has K number of elements         // Function to count the number of    // ways to divide the number N in groups    function countWaystoDivide(n, k)    {        if (n < k)            return 0; // When n is less than k, No way to divide                      // into groups        let dp = new Array(n + 1);        for(let i = 0; i < n + 1; i++)        {            dp[i] = new Array(k + 1);            for(let j = 0; j < k + 1; j++)            {                dp[i][j] = 0;            }        }         for (let i = 1; i <= n; i++)            dp[i][1]                = 1; // exact one way to divide n to 1 group        dp[0][0] = 1;         for (let i = 1; i <= n; i++) {            for (let j = 2; j <= k; j++) {                if (i >= j)                    dp[i][j] = dp[i - j][j] + dp[i - 1][j - 1];                else                    dp[i][j]                        = dp[i - 1][j - 1]; // i<j so dp[i-j][j]                                            // becomes zero            }        }        return dp[n][k]; // returning number of ways to divide N                         // in k groups    }         let N = 8;    let K = 4;      document.write(countWaystoDivide(N, K)); // This code is contributed by mukesh07.</script>
5
Time complexity: O(N * K)Auxiliary Space:  O(N * K)
king_tsar
Rajput-Ji
GauravRajput1
29AjayKumar
mayanktyagi1709
TarunSingh2
unknown2108
saurabh1990aror
pankajsharmagfg
kapilag
akhil14shukla
sweetyty
prachisoda1234
mukesh07
rohitsingh07052
rameshtravel07
ashutoshsinghgeeksforgeeks
Algorithms
Competitive Programming
Dynamic Programming
Mathematical
Recursion
Dynamic Programming
Mathematical
Recursion
Algorithms
Writing code in comment?
Please use ide.geeksforgeeks.org,
generate link and share the link here.
SDE SHEET - A Complete Guide for SDE Preparation
DSA Sheet by Love Babbar
Introduction to Algorithms
Recursive Practice Problems with Solutions
Quick Sort vs Merge Sort
Competitive Programming - A Complete Guide
Practice for cracking any coding interview
Arrow operator -> in C/C++ with Examples
Top 10 Algorithms and Data Structures for Competitive Programming
Bits manipulation (Important tactics)