Number of ways to divide a given number as a set of integers in decreasing order

Given two numbers a and m. The task is to find the number of ways in which a can be represented by a set \{n_1, n_2, ...., n_c\} such that a >= n_1 > n_2 > ... > n_m > 0 and the summation of these numbers is equal to a. Also  1 <= c <= m (maximum size of the set cannot exceed m).


Input : a = 4, m = 4
Output : 2 –> ({4}, {3, 1})
Note: {2, 2} is not a valid set as values are not in decreasing order

Input : a = 7, m = 5
Output : 5 –> ({7}, {6, 1}, {5, 2}, {4, 3}, {4, 2, 1})

Approach: This problem can be solved by Divide and Conquer using a recursive approach which follows the following conditions:

  • If a is equal to zero, one solution has been found.
  • If a > 0 and m == 0, this set violates the condition as no further values can be added in the set.
  • If calculation has already been done for given values of a, m and prev (last value included in the current set), return that value.
  • Start a loop from i = a till 0 and if i < prev, count the number of solutions if we include i in the current set and return it.

Below is the implementation of the above approach:





# Python3 code to calculate the number of ways 
# in which a given number can be represented 
# as set of finite numbers
# Import function to initialize the dictionary
from collections import defaultdict
# Initialize dictionary which is used 
# to check if given solution is already 
# visited or not to avoid
# calculating it again
visited = defaultdict(lambda : False)
# Initialize dictionary which is used to
# store the number of ways in which solution
# can be obtained for given values
numWays = defaultdict(lambda : 0)
# This function returns the total number
# of sets which satisfy given criteria
# a --> number to be divided into sets
# m --> maximum possible size of the set
# x --> previously selected value
def countNumOfWays(a, m, prev):
    # number is divided properly and
    # hence solution is obtained
    if a == 0:
        return 1
    # Solution can't be obtained
    elif a > 0 and m == 0:
        return 0
    # Return the solution if it has
    # already been calculated
    elif visited[(a, m, prev)] == True:
        return numWays[(a, m, prev)]
        visited[(a, m, prev)] = True
        for i in range(a, -1, -1):
            # Continue only if current value is 
            # smaller compared to previous value
            if i < prev:
                numWays[(a,m,prev)] += countNumOfWays(a-i,m-1,i)
        return numWays[(a, m, prev)]
# Values of 'a' and 'm' for which
# solution is to be found
# MAX_CONST is extremely large value 
# used for first comparison in the function
a, m, MAX_CONST = 7, 5, 10**5
print(countNumOfWays(a, m, MAX_CONST))




Time Complexity: O(a*log(a))

My Personal Notes arrow_drop_up

I like solving puzzles

If you like GeeksforGeeks and would like to contribute, you can also write an article using or mail your article to See your article appearing on the GeeksforGeeks main page and help other Geeks.

Please Improve this article if you find anything incorrect by clicking on the "Improve Article" button below.