Open In App

Number of ways to get a given sum with n number of m-faced dices

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given n dices, each with m faces, numbered from 1 to m, find the number of ways to get a given sum X. X is the summation of values on each face when all the dice are thrown.
Examples: 
 

Input : faces = 4 throws = 2 sum =4 
Output :
Ways to reach sum equal to 4 in 2 throws can be { (1, 3), (2, 2), (3, 1) }
Input : faces = 6 throws = 3 sum = 12 
Output : 25
 

 

Approach: 
Basically, it is asked to achieve sum in n number of operations using the values in the range [1…m]. 
Use dynamic programming top-down methodology for this problem. The steps are: 
 

  • Base Cases: 
    1. If (sum == 0 and noofthrowsleft ==0) return 1 . It means that sum x has 
      been achieved.
    2. If (sum < 0 and noofthrowsleft ==0) return 0.It means that sum x has not 
      been achieved in all throws.
  • If present sum with present noofthrowsleft is already achieved then return it from the table instead of re computation.
  • Then we will loop through all the values of faces from i=[1..m] and recursively moving to achieve sum-i and also decrease the noofthrowsleft by 1.
  • Finally, we will store current values in the dp array

Below is the implementation of the above method: 
 

C++




// C++ function to calculate the number of
// ways to achieve sum x in n no of throws
#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
int dp[55][55];
 
// Function to calculate recursively the
// number of ways to get sum in given
// throws and [1..m] values
int NoofWays(int face, int throws, int sum)
{
    // Base condition 1
    if (sum == 0 && throws == 0)
        return 1;
 
    // Base condition 2
    if (sum < 0 || throws == 0)
        return 0;
 
    // If value already calculated donot
    // move into re-computation
    if (dp[throws][sum] != -1)
        return dp[throws][sum];
 
    int ans = 0;
    for (int i = 1; i <= face; i++) {
 
        // Recursively moving for sum-i in
        // throws-1 no of throws left
        ans += NoofWays(face, throws - 1, sum - i);
    }
 
    // Inserting present values in dp
    return dp[throws][sum] = ans;
}
 
// Driver function
int main()
{
    int faces = 6, throws = 3, sum = 12;
 
    memset(dp, -1, sizeof dp);
 
    cout << NoofWays(faces, throws, sum) << endl;
 
    return 0;
}


Java




// Java function to calculate the number of
// ways to achieve sum x in n no of throwsVal
class GFG
{
 
    static int mod = 1000000007;
    static int[][] dp = new int[55][55];
 
    // Function to calculate recursively the
    // number of ways to get sum in given
    // throwsVal and [1..m] values
    static int NoofWays(int face, int throwsVal, int sum)
    {
        // Base condition 1
        if (sum == 0 && throwsVal == 0)
        {
            return 1;
        }
 
        // Base condition 2
        if (sum < 0 || throwsVal == 0)
        {
            return 0;
        }
 
        // If value already calculated donot
        // move into re-computation
        if (dp[throwsVal][sum] != -1)
        {
            return dp[throwsVal][sum];
        }
 
        int ans = 0;
        for (int i = 1; i <= face; i++)
        {
 
            // Recursively moving for sum-i in
            // throwsVal-1 no of throwsVal left
            ans += NoofWays(face, throwsVal - 1, sum - i);
        }
 
        // Inserting present values in dp
        return dp[throwsVal][sum] = ans;
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int faces = 6, throwsVal = 3, sum = 12;
        for (int i = 0; i < 55; i++)
        {
            for (int j = 0; j < 55; j++)
            {
                dp[i][j] = -1;
            }
        }
 
        System.out.println(NoofWays(faces, throwsVal, sum));
    }
}
 
// This code is contributed by 29AjayKumar


Python3




# Python3 function to calculate the number of
# ways to achieve sum x in n no of throws
import numpy as np
 
mod = 1000000007;
 
dp = np.zeros((55,55));
 
# Function to calculate recursively the
# number of ways to get sum in given
# throws and [1..m] values
def NoofWays(face, throws, sum) :
 
    # Base condition 1
    if (sum == 0 and throws == 0) :
        return 1;
 
    # Base condition 2
    if (sum < 0 or throws == 0) :
        return 0;
 
    # If value already calculated donot
    # move into re-computation
    if (dp[throws][sum] != -1) :
        return dp[throws][sum];
 
    ans = 0;
    for i in range(1, face + 1) :
 
        # Recursively moving for sum-i in
        # throws-1 no of throws left
        ans += NoofWays(face, throws - 1, sum - i);
 
    # Inserting present values in dp
    dp[throws][sum] = ans;
     
    return ans;
 
 
# Driver function
if __name__ == "__main__" :
 
    faces = 6; throws = 3; sum = 12;
 
    for i in range(55) :
        for j in range(55) :
            dp[i][j] = -1
 
    print(NoofWays(faces, throws, sum)) ;
     
# This code is contributed by AnkitRai01


C#




// C# function to calculate the number of
// ways to achieve sum x in n no of throwsVal
using System;
 
class GFG
{
     
    static int[,]dp = new int[55,55];
 
    // Function to calculate recursively the
    // number of ways to get sum in given
    // throwsVal and [1..m] values
    static int NoofWays(int face, int throwsVal, int sum)
    {
        // Base condition 1
        if (sum == 0 && throwsVal == 0)
        {
            return 1;
        }
 
        // Base condition 2
        if (sum < 0 || throwsVal == 0)
        {
            return 0;
        }
 
        // If value already calculated donot
        // move into re-computation
        if (dp[throwsVal,sum] != -1)
        {
            return dp[throwsVal,sum];
        }
 
        int ans = 0;
        for (int i = 1; i <= face; i++)
        {
 
            // Recursively moving for sum-i in
            // throwsVal-1 no of throwsVal left
            ans += NoofWays(face, throwsVal - 1, sum - i);
        }
 
        // Inserting present values in dp
        return dp[throwsVal,sum] = ans;
    }
 
    // Driver code
    static public void Main ()
    {
        int faces = 6, throwsVal = 3, sum = 12;
        for (int i = 0; i < 55; i++)
        {
            for (int j = 0; j < 55; j++)
            {
                dp[i,j] = -1;
            }
        }
 
    Console.WriteLine(NoofWays(faces, throwsVal, sum));
    }
}
 
// This code is contributed by ajit.


Javascript




<script>
 
// Javascript function to calculate the number of
// ways to achieve sum x in n no of throws
 
const mod = 1000000007;
let dp = new Array(55);
for (let i = 0; i < 55; i++)
    dp[i] = new Array(55).fill(-1);
 
// Function to calculate recursively the
// number of ways to get sum in given
// throws and [1..m] values
function NoofWays(face, throws, sum)
{
    // Base condition 1
    if (sum == 0 && throws == 0)
        return 1;
 
    // Base condition 2
    if (sum < 0 || throws == 0)
        return 0;
 
    // If value already calculated donot
    // move into re-computation
    if (dp[throws][sum] != -1)
        return dp[throws][sum];
 
    let ans = 0;
    for (let i = 1; i <= face; i++) {
 
        // Recursively moving for sum-i in
        // throws-1 no of throws left
        ans += NoofWays(face, throws - 1, sum - i);
    }
 
    // Inserting present values in dp
    return dp[throws][sum] = ans;
}
 
// Driver function
    let faces = 6, throws = 3, sum = 12;
    document.write(NoofWays(faces, throws, sum));
 
</script>


Output: 

25

 

Time complexity : O(throws*faces*sum) 
Space complexity : O(faces*sum)
 

Efficient approach : Using DP Tabulation method ( Iterative approach )

The approach to solve this problem is same but DP tabulation(bottom-up) method is better then Dp + memoization(top-down) because memoization method needs extra stack space of recursion calls.

Steps to solve this problem :

  • Create a 2D array DP to store the solution of the subproblems and initialize it with 0.
  • Initialize the DP with base cases.
  • Now Iterate over subproblems to get the value of current problem form previous computation of subproblems stored in DP.
  • Return the final solution stored in dp[throws][sum] .

Implementation :

C++




// c++ code above approach
 
#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
 
int dp[55][55];
 
// Function to calculate recursively the
// number of ways to get sum in given
// throws and [1..m] values
int NoofWays(int face, int throws, int sum)
{
    memset(dp, 0, sizeof dp);
 
    // Initialize base conditions
    for (int i = 1; i <= face && i <= sum; i++)
        dp[1][i] = 1;
     
    // iterate over subproblems to get the current solution
    for (int t = 2; t <= throws; t++)
    {
        for (int s = 1; s <= sum; s++)
        {
            for (int i = 1; i <= face && i < s; i++)
            {  
                 
                // get current value from previous computations
                dp[t][s] += dp[t - 1][s - i];
                dp[t][s] %= mod;
            }
        }
    }
     
    // return answer
    return dp[throws][sum];
}
     
// Driver code
int main()
{
    int faces = 6, throws = 3, sum = 12;
     
    // function call
    cout << NoofWays(faces, throws, sum) << endl;
 
    return 0;
}


Java




import java.util.*;
 
public class Main {
    static int mod = 1000000007;
    static int[][] dp = new int[55][55];
 
    // Function to calculate recursively the
    // number of ways to get sum in given
    // throws and [1..m] values
    static int NoofWays(int face, int throws_, int sum)
    {
        Arrays.stream(dp).forEach(a -> Arrays.fill(a, 0));
 
        // Initialize base conditions
        for (int i = 1; i <= face && i <= sum; i++)
            dp[1][i] = 1;
 
        // iterate over subproblems to get the current
        // solution
        for (int t = 2; t <= throws_; t++) {
            for (int s = 1; s <= sum; s++) {
                for (int i = 1; i <= face && i < s; i++) {
 
                    // get current value from previous
                    // computations
                    dp[t][s] += dp[t - 1][s - i];
                    dp[t][s] %= mod;
                }
            }
        }
 
        // return answer
        return dp[throws_][sum];
    }
 
    // Driver code
    public static void main(String[] args)
    {
        int faces = 6, throws_ = 3, sum = 12;
 
        // function call
        System.out.println(NoofWays(faces, throws_, sum));
    }
}


Python3




mod = 1000000007
 
# Function to calculate recursively the
# number of ways to get sum in given
# throws and [1..m] values
def NoofWays(face, throws, sum):
    dp = [[0 for i in range(sum + 1)] for j in range(throws + 1)]
 
    # Initialize base conditions
    for i in range(1, face + 1):
        if i <= sum:
            dp[1][i] = 1
 
    # iterate over subproblems to get the current solution
    for t in range(2, throws + 1):
        for s in range(1, sum + 1):
            for i in range(1, face + 1):
                if i < s:
                    # get current value from previous computations
                    dp[t][s] += dp[t - 1][s - i]
                    dp[t][s] %= mod
 
    # return answer
    return dp[throws][sum]
 
 
faces = 6
throws = 3
sum = 12
 
# function call
print(NoofWays(faces, throws, sum))


C#




// C# code for above approach
 
using System;
 
class MainClass {
 
    // Function to calculate recursively the
    // number of ways to get sum in given
    // throws and [1..m] values
    public static int NoofWays(int face, int throws, int sum)
    {
        int[, ] dp = new int[55, 55];
 
        // Initialize base conditions
        for (int i = 1; i <= face && i <= sum; i++)
            dp[1, i] = 1;
 
        // iterate over subproblems to
        // get the current solution
        for (int t = 2; t <= throws; t++) {
            for (int s = 1; s <= sum; s++) {
                for (int i = 1; i <= face && i < s; i++) {
 
                    // Get current value from
                    // previous computations
                    dp[t, s] += dp[t - 1, s - i];
                    dp[t, s] %= 1000000007;
                }
            }
        }
 
        // return answer
        return dp[throws, sum];
    }
 
    // Driver code
    public static void Main(string[] args)
    {
        int faces = 6, throws = 3, sum = 12;
        Console.WriteLine(NoofWays(faces, throws, sum));
    }
}


Javascript




// JavaScript code for the approach
function NoofWays(face, throws, sum) {
    const mod = 1000000007;
    const dp = new Array(55).fill().map(() => new Array(55).fill(0));
     
    // Initialize base conditions
    for (let i = 1; i <= face && i <= sum; i++) {
        dp[1][i] = 1;
    }
 
    // iterate over subproblems to get the current solution
    for (let t = 2; t <= throws; t++) {
        for (let s = 1; s <= sum; s++) {
            for (let i = 1; i <= face && i < s; i++) {
             
                // get current value from previous computations
                dp[t][s] += dp[t - 1][s - i];
                dp[t][s] %= mod;
            }
        }
    }
 
    // return answer
    return dp[throws][sum];
}
 
// Driver code
const faces = 6;
const throws = 3;
const sum = 12;
 
// function call
console.log(NoofWays(faces, throws, sum));
 
// This code is contributed by user_dtewbxkn77n


Output

25

Time complexity : O(throws*faces*sum) 
Auxiliary Space : O(throws*sum)



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