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).

Examples:

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:

filter_none

edit
close

play_arrow

link
brightness_4
code

# 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)]
      
    else:
        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))

chevron_right


Output:

5

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 contribute.geeksforgeeks.org or mail your article to contribute@geeksforgeeks.org. 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.