Open In App

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

Improve
Improve
Like Article
Like
Save
Share
Report

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: 

C++

// C++ code to calculate the number of ways
// in which a given number can be represented
// as set of finite numbers
#include <bits/stdc++.h>
#include <unordered_map>
using namespace std;
 
// Initialize dictionary which is used
// to check if given solution is already
// visited or not to avoid
// calculating it again
unordered_map<string, bool> visited;
 
// Initialize dictionary which is used to
// store the number of ways in which solution
// can be obtained for given values
unordered_map<string, int> numWays;
 
// 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
int countNumOfWays(int a, int m, int prev)
{
  // number is divided properly and
  // hence solution is obtained
  if (a == 0)
    return 1;
 
  // Solution can't be obtained
  if (a > 0 && m == 0)
    return 0;
 
  // Return the solution if it has
  // already been calculated
  string key = to_string(a) + "|" + to_string(m) + "|" + to_string(prev);
  if (visited.find(key) != visited.end())
    return numWays[key];
 
  visited[key] = true;
  for (int i = a; i >= 0; i--)
  {
    // Continue only if current value is
    // smaller compared to previous value
    if (i < prev)
      numWays[key] += countNumOfWays(a - i, m - 1, i);
  }
 
  return numWays[key];
}
 
// Values of 'a' and 'm' for which
// solution is to be found
int a = 7, m = 5, MAX_CONST = 10e5;
 
// Driver code
int main()
{
  cout << countNumOfWays(a, m, MAX_CONST) << endl;
  return 0;
}

                    

Python3

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

                    

Javascript

// Javascript 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
const visited = new Map();
const numWays = new Map();
 
// 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
function countNumOfWays(a, m, prev) {
  // number is divided properly and
  // hence solution is obtained
  if (a == 0) {
    return 1;
  }
  // Solution can't be obtained
  else if (a > 0 && m == 0) {
    return 0;
  }
  // Return the solution if it has
  // already been calculated
  else if (visited.has([a, m, prev])) {
    return numWays.get([a, m, prev]);
  } else {
    visited.set([a, m, prev], true);
 
    let totalWays = 0;
    for (let i = a; i >= 0; i--) {
      // Continue only if current value is
      // smaller compared to previous value
      if (i < prev) {
        totalWays += countNumOfWays(a - i, m - 1, i);
      }
    }
    numWays.set([a, m, prev], totalWays);
    return totalWays;
  }
}
 
// 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
const a = 7,
  m = 5,
  MAX_CONST = 10 ** 5;
console.log(countNumOfWays(a, m, MAX_CONST));

                    

Java

import java.util.*;
 
public class Main {
 
    // Initialize dictionary which is used
    // to check if given solution is already
    // visited or not to avoid
    // calculating it again
    static Map<String, Boolean> visited = new HashMap<>();
 
    // Initialize dictionary which is used to
    // store the number of ways in which solution
    // can be obtained for given values
    static Map<String, Integer> numWays = new HashMap<>();
 
    // 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
    static int countNumOfWays(int a, int m, int prev)
    {
      // number is divided properly and
      // hence solution is obtained
      if (a == 0)
        return 1;
 
      // Solution can't be obtained
      if (a > 0 && m == 0)
        return 0;
 
      // Return the solution if it has
      // already been calculated
      String key = a + "|" + m + "|" + prev;
      if (visited.containsKey(key))
        return numWays.get(key);
 
      visited.put(key, true);
      int ways = 0;
      for (int i = a; i >= 0; i--)
      {
        // Continue only if current value is
        // smaller compared to previous value
        if (i < prev)
          ways += countNumOfWays(a - i, m - 1, i);
      }
 
      numWays.put(key, ways);
      return ways;
    }
 
    // Values of 'a' and 'm' for which
    // solution is to be found
    static int a = 7, m = 5, MAX_CONST = 10^5;
 
    // Driver code
    public static void main(String[] args)
    {
      System.out.println(countNumOfWays(a, m, MAX_CONST));
    }
}

                    

C#

using System;
using System.Collections.Generic;
 
class GFG
{
  // Initialize dictionary which is used
  // to check if given solution is already
  // visited or not to avoid
  // calculating it again
  static Dictionary<string, bool> visited = new Dictionary<string, bool>();
 
 
  // Initialize dictionary which is used to
  // store the number of ways in which solution
  // can be obtained for given values
  static Dictionary<string, int> numWays = new Dictionary<string, int>();
 
  // 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
  static int CountNumOfWays(int a, int m, int prev)
  {
      // number is divided properly and
      // hence solution is obtained
      if (a == 0)
          return 1;
 
      // Solution can't be obtained
      if (a > 0 && m == 0)
          return 0;
 
      // Return the solution if it has
      // already been calculated
      string key = a + "|" + m + "|" + prev;
      if (visited.ContainsKey(key))
          return numWays[key];
 
      visited.Add(key, true);
      int ways = 0;
      for (int i = a; i >= 0; i--)
      {
          // Continue only if current value is
          // smaller compared to previous value
          if (i < prev)
              ways += CountNumOfWays(a - i, m - 1, i);
      }
 
      numWays.Add(key, ways);
      return ways;
  }
 
  // Values of 'a' and 'm' for which
  // solution is to be found
  static int a = 7, m = 5, MAX_CONST = (int)Math.Pow(10, 5);
 
  // Driver code
  public static void Main(string[] args)
  {
      Console.WriteLine(CountNumOfWays(a, m, MAX_CONST));
  }
 
}

                    
Output:
5

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



Last Updated : 27 Mar, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads