Related Articles
Dice Throw | DP-30
• Difficulty Level : Hard
• Last Updated : 11 Jul, 2019

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

## Recommended: Please solve it on “PRACTICE ” first, before moving on to the solution.

The Naive approach is to find all the possible combinations of values from n dice and keep on counting the results that sum to X.

This problem can be efficiently solved using Dynamic Programming (DP).

```Let the function to find X from n dice is: Sum(m, n, X)
The function can be represented as:
Sum(m, n, X) = Finding Sum (X - 1) from (n - 1) dice plus 1 from nth dice
+ Finding Sum (X - 2) from (n - 1) dice plus 2 from nth dice
+ Finding Sum (X - 3) from (n - 1) dice plus 3 from nth dice
...................................................
...................................................
...................................................
+ Finding Sum (X - m) from (n - 1) dice plus m from nth dice

So we can recursively write Sum(m, n, x) as following
Sum(m, n, X) = Sum(m, n - 1, X - 1) +
Sum(m, n - 1, X - 2) +
.................... +
Sum(m, n - 1, X - m)```

Why DP approach?
The above problem exhibits overlapping subproblems. See the below diagram. Also, see this recursive implementation. Let there be 3 dice, each with 6 faces and we need to find the number of ways to get sum 8: ```Sum(6, 3, 8) = Sum(6, 2, 7) + Sum(6, 2, 6) + Sum(6, 2, 5) +
Sum(6, 2, 4) + Sum(6, 2, 3) + Sum(6, 2, 2)

To evaluate Sum(6, 3, 8), we need to evaluate Sum(6, 2, 7) which can
recursively written as following:
Sum(6, 2, 7) = Sum(6, 1, 6) + Sum(6, 1, 5) + Sum(6, 1, 4) +
Sum(6, 1, 3) + Sum(6, 1, 2) + Sum(6, 1, 1)

We also need to evaluate Sum(6, 2, 6) which can recursively written
as following:
Sum(6, 2, 6) = Sum(6, 1, 5) + Sum(6, 1, 4) + Sum(6, 1, 3) +
Sum(6, 1, 2) + Sum(6, 1, 1)
..............................................
..............................................
Sum(6, 2, 2) = Sum(6, 1, 1)```

Please take a closer look at the above recursion. The sub-problems in RED are solved first time and sub-problems in BLUE are solved again (exhibit overlapping sub-problems). Hence, storing the results of the solved sub-problems saves time.

Following is implementation of Dynamic Programming approach.

## C++

 `// C++ program to find number of ways to get sum 'x' with 'n'``// dice where every dice has 'm' faces``#include ``#include ``using` `namespace` `std;`` ` `//  The main function that returns number of ways to get sum 'x'``//  with 'n' dice and 'm' with m faces.``int` `findWays(``int` `m, ``int` `n, ``int` `x)``{``    ``// Create a table to store results of subproblems.  One extra ``    ``// row and column are used for simpilicity (Number of dice``    ``// is directly used as row index and sum is directly used``    ``// as column index).  The entries in 0th row and 0th column``    ``// are never used.``    ``int` `table[n + 1][x + 1];``    ``memset``(table, 0, ``sizeof``(table)); ``// Initialize all entries as 0`` ` `    ``// Table entries for only one dice``    ``for` `(``int` `j = 1; j <= m && j <= x; j++)``        ``table[j] = 1;`` ` `    ``// Fill rest of the entries in table using recursive relation``    ``// i: number of dice, j: sum``    ``for` `(``int` `i = 2; i <= n; i++)``        ``for` `(``int` `j = 1; j <= x; j++)``            ``for` `(``int` `k = 1; k <= m && k < j; k++)``                ``table[i][j] += table[i-1][j-k];`` ` `    ``/* Uncomment these lines to see content of table``    ``for (int i = 0; i <= n; i++)``    ``{``      ``for (int j = 0; j <= x; j++)``        ``cout << table[i][j] << " ";``      ``cout << endl;``    ``} */``    ``return` `table[n][x];``}`` ` `// Driver program to test above functions``int` `main()``{``    ``cout << findWays(4, 2, 1) << endl;``    ``cout << findWays(2, 2, 3) << endl;``    ``cout << findWays(6, 3, 8) << endl;``    ``cout << findWays(4, 2, 5) << endl;``    ``cout << findWays(4, 3, 5) << endl;`` ` `    ``return` `0;``}`

## Java

 `// Java program to find number of ways to get sum 'x' with 'n' ``// dice where every dice has 'm' faces ``import` `java.util.*;``import` `java.lang.*;``import` `java.io.*;`` ` `class` `GFG {``    ``/* The main function that returns the number of ways to get sum 'x' with 'n' dice and 'm' with m faces. */``    ``public` `static` `long` `findWays(``int` `m, ``int` `n, ``int` `x){``         ` `    ``/* Create a table to store the results of subproblems. ``    ``One extra row and column are used for simplicity ``    ``(Number of dice is directly used as row index and sum is directly used as column index). ``    ``The entries in 0th row and 0th column are never used. */``    ``long``[][] table = ``new` `long``[n+``1``][x+``1``];``         ` `    ``/* Table entries for only one dice */``    ``for``(``int` `j = ``1``; j <= m && j <= x; j++)``                ``table[``1``][j] = ``1``;``             ` `    ``/* Fill rest of the entries in table using recursive relation ``    ``i: number of dice, j: sum */``    ``for``(``int` `i = ``2``; i <= n;i ++){``                ``for``(``int` `j = ``1``; j <= x; j++){``                    ``for``(``int` `k = ``1``; k < j && k <= m; k++)``                        ``table[i][j] += table[i-``1``][j-k];``                ``}``        ``}``         ` `        ``/* Uncomment these lines to see content of table ``        ``for(int i = 0; i< n+1; i++){``            ``for(int j = 0; j< x+1; j++)``                ``System.out.print(dt[i][j] + " ");``            ``System.out.println();``        ``} */``         ` `        ``return` `table[n][x];``    ``}``     ` `    ``// Driver Code``    ``public` `static` `void` `main (String[] args) {``        ``System.out.println(findWays(``4``, ``2``, ``1``)); ``        ``System.out.println(findWays(``2``, ``2``, ``3``)); ``        ``System.out.println(findWays(``6``, ``3``, ``8``)); ``        ``System.out.println(findWays(``4``, ``2``, ``5``)); ``        ``System.out.println(findWays(``4``, ``3``, ``5``)); ``    ``}``}`` ` `// This code is contributed by MaheshwariPiyush`

## Python3

 `# Python3 program to find the number of ways to get sum 'x' with 'n' dice``# where every dice has 'm' faces`` ` `# The main function that returns number of ways to get sum 'x' ``# with 'n' dice and 'm' with m faces.``def` `findWays(m,n,x):``    ``# Create a table to store results of subproblems. One extra ``    ``# row and column are used for simpilicity (Number of dice ``    ``# is directly used as row index and sum is directly used ``    ``# as column index). The entries in 0th row and 0th column ``    ``# are never used.``    ``table``=``[[``0``]``*``(x``+``1``) ``for` `i ``in` `range``(n``+``1``)] ``#Initialize all entries as 0``     ` `    ``for` `j ``in` `range``(``1``,``min``(m``+``1``,x``+``1``)): ``#Table entries for only one dice``        ``table[``1``][j]``=``1``         ` `    ``# Fill rest of the entries in table using recursive relation ``    ``# i: number of dice, j: sum``    ``for` `i ``in` `range``(``2``,n``+``1``):``        ``for` `j ``in` `range``(``1``,x``+``1``):``            ``for` `k ``in` `range``(``1``,``min``(m``+``1``,j)):``                ``table[i][j]``+``=``table[i``-``1``][j``-``k]``     ` `    ``#print(dt)``    ``# Uncomment above line to see content of table``     ` `    ``return` `table[``-``1``][``-``1``]``     ` `# Driver code``print``(findWays(``4``,``2``,``1``))``print``(findWays(``2``,``2``,``3``))``print``(findWays(``6``,``3``,``8``))``print``(findWays(``4``,``2``,``5``))``print``(findWays(``4``,``3``,``5``))`` ` `# This code is contributed by MaheshwariPiyush`

## C#

 `// C# program to find number ``// of ways to get sum 'x' ``// with 'n' dice where every ``// dice has 'm' faces``using` `System;`` ` `class` `GFG``{``// The main function that returns ``// number of ways to get sum 'x'``// with 'n' dice and 'm' with m faces.``static` `int` `findWays(``int` `m, ``                    ``int` `n, ``int` `x)``{``    ``// Create a table to store ``    ``// results of subproblems. ``    ``// row and column are used ``    ``// for simpilicity (Number ``    ``// of dice is directly used ``    ``// as row index and sum is ``    ``// directly used as column``    ``// index). The entries in 0th``    ``// row and 0th column are ``    ``// never used.``    ``int``[,] table = ``new` `int``[n + 1, ``                           ``x + 1];``                            ` `    ``// Initialize all ``    ``// entries as 0``    ``for` `(``int` `i = 0; i <= n; i++)``    ``for` `(``int` `j = 0; j <= x; j++)``    ``table[i, j] = 0;``     ` `    ``// Table entries for ``    ``// only one dice``    ``for` `(``int` `j = 1; ``             ``j <= m && j <= x; j++)``        ``table[1, j] = 1;`` ` `    ``// Fill rest of the entries ``    ``// in table using recursive ``    ``// relation i: number of ``    ``// dice, j: sum``    ``for` `(``int` `i = 2; i <= n; i++)``        ``for` `(``int` `j = 1; j <= x; j++)``            ``for` `(``int` `k = 1; ``                     ``k <= m && k < j; k++)``                ``table[i, j] += table[i - 1, ``                                     ``j - k];`` ` `    ``/* Uncomment these lines to``    ``see content of table``    ``for (int i = 0; i <= n; i++)``    ``{``    ``for (int j = 0; j <= x; j++)``        ``cout << table[i][j] << " ";``    ``cout << endl;``    ``} */``    ``return` `table[n, x];``}`` ` `// Driver Code``public` `static` `void` `Main()``{``    ``Console.WriteLine(findWays(4, 2, 1));``    ``Console.WriteLine(findWays(2, 2, 3));``    ``Console.WriteLine(findWays(6, 3, 8));``    ``Console.WriteLine(findWays(4, 2, 5));``    ``Console.WriteLine(findWays(4, 3, 5));``}``}`` ` `// This code is contributed by mits.`

## PHP

 ``

Output :
```0
2
21
4
6```

Time Complexity: O(m * n * x) where m is number of faces, n is number of dice and x is given sum.

We can add the following two conditions at the beginning of findWays() to improve performance of the program for extreme cases (x is too high or x is too low)

 `// When x is so high that sum can not go beyond x even when we ``// get maximum value in every dice throw. ``if` `(m*n <= x)``    ``return` `(m*n == x);` `// When x is too low``if` `(n >= x)``    ``return` `(n == x);`

With above conditions added, time complexity becomes O(1) when x >= m*n or when x <= n.

Following is the implementation of the Optimized Dynamic Programming approach.

## C++

 `//  C++ program``//  The main function that returns number of ways to get sum 'x'``//  with 'n' dice and 'm' with m faces.``#include``using` `namespace` `std;`` ` `long` `findWays(``int` `f, ``int` `d, ``int` `s)``{``    ``// Create a table to store results of subproblems. One extra``    ``// row and column are used for simpilicity (Number of dice``    ``// is directly used as row index and sum is directly used``    ``// as column index). The entries in 0th row and 0th column``    ``// are never used.``    ``long` `mem[d + 1][s + 1];``    ``memset``(mem,0,``sizeof` `mem);``    ``// Table entries for no dices``    ``// If you do not have any data, then the value must be 0, so the result is 1``    ``mem = 1;``    ``// Iterate over dices``    ``for` `(``int` `i = 1; i <= d; i++)``    ``{``        ``// Iterate over sum``        ``for` `(``int` `j = i; j <= s; j++)``        ``{``            ``// The result is obtained in two ways, pin the current dice and spending 1 of the value,``            ``// so we have mem[i-1][j-1] remaining combinations, to find the remaining combinations we``            ``// would have to pin the values ??above 1 then we use mem[i][j-1] to sum all combinations``            ``// that pin the remaining j-1's. But there is a way, when "j-f-1> = 0" we would be adding``            ``// extra combinations, so we remove the combinations that only pin the extrapolated dice face and``            ``// subtract the extrapolated combinations.``            ``mem[i][j] = mem[i][j - 1] + mem[i - 1][j - 1];``            ``if` `(j - f - 1 >= 0)``                ``mem[i][j] -= mem[i - 1][j - f - 1];``        ``}``    ``}``    ``return` `mem[d][s];``}`` ` `// Driver code``int` `main(``void``)``{``    ``cout << findWays(4, 2, 1) << endl;``    ``cout << findWays(2, 2, 3) << endl;``    ``cout << findWays(6, 3, 8) << endl;``    ``cout << findWays(4, 2, 5) << endl;``    ``cout << findWays(4, 3, 5) << endl;``    ``return` `0;``}`` ` `// This code is contributed by ankush_953`

## Java

 `/**`` ``* The main function that returns number of ways to get sum 'x'`` ``* with 'n' dice and 'm' with m faces.`` ``* `` ``* @author Pedro H. Chaves `` ``*/``public` `class` `GFG {``     ` `    ``/**``     ``* Count ways``     ``* ``     ``* @param f``     ``* @param d``     ``* @param s``     ``* @return``     ``*/``    ``public` `static` `long` `findWays(``int` `f, ``int` `d, ``int` `s) {``        ``// Create a table to store results of subproblems.  One extra ``        ``// row and column are used for simpilicity (Number of dice``        ``// is directly used as row index and sum is directly used``        ``// as column index).  The entries in 0th row and 0th column``        ``// are never used.``        ``long` `mem[][] = ``new` `long``[d + ``1``][s + ``1``];``        ``// Table entries for no dices``        ``// If you do not have any data, then the value must be 0, so the result is 1``        ``mem[``0``][``0``] = ``1``;``        ``// Iterate over dices``        ``for``(``int` `i=``1``; i<=d; i++) {``            ``// Iterate over sum``            ``for``(``int` `j=i; j<=s; j++) {``                ``// The result is obtained in two ways, pin the current dice and spending 1 of the value, ``                ``// so we have mem[i-1][j-1] remaining combinations, to find the remaining combinations we ``                ``// would have to pin the values ??above 1 then we use mem[i][j-1] to sum all combinations ``                ``// that pin the remaining j-1's. But there is a way, when "j-f-1> = 0" we would be adding ``                ``// extra combinations, so we remove the combinations that only pin the extrapolated dice face and ``                ``// subtract the extrapolated combinations.``                ``mem[i][j] = mem[i][j-``1``] + mem[i-``1``][j-``1``];``                ``if``(j-f-``1` `>= ``0``)``                    ``mem[i][j] -= mem[i-``1``][j-f-``1``];``            ``}``        ``}``        ``return` `mem[d][s];``    ``}``     ` `     ` `    ``/**``     ``* Main``     ``* ``     ``* @param args``     ``*/``    ``public` `static` `void` `main(String[] args) {``        ``System.out.println(findWays(``4``, ``2``, ``1``));``        ``System.out.println(findWays(``2``, ``2``, ``3``));``        ``System.out.println(findWays(``6``, ``3``, ``8``));``        ``System.out.println(findWays(``4``, ``2``, ``5``));``        ``System.out.println(findWays(``4``, ``3``, ``5``));``    ``}``}`

## Python3

 `#  Python program``#  The main function that returns number of ways to get sum 'x'``#  with 'n' dice and 'm' with m faces.`` ` ` ` `def` `findWays(f, d, s):``    ``# Create a table to store results of subproblems. One extra``    ``# row and column are used for simpilicity (Number of dice``    ``# is directly used as row index and sum is directly used``    ``# as column index). The entries in 0th row and 0th column``    ``# are never used.``    ``mem ``=` `[[``0` `for` `i ``in` `range``(s``+``1``)] ``for` `j ``in` `range``(d``+``1``)]``    ``# Table entries for no dices``    ``# If you do not have any data, then the value must be 0, so the result is 1``    ``mem[``0``][``0``] ``=` `1``    ``# Iterate over dices``    ``for` `i ``in` `range``(``1``, d``+``1``):`` ` `        ``# Iterate over sum``        ``for` `j ``in` `range``(``1``, s``+``1``):``            ``# The result is obtained in two ways, pin the current dice and spending 1 of the value,``            ``# so we have mem[i-1][j-1] remaining combinations, to find the remaining combinations we``            ``# would have to pin the values ??above 1 then we use mem[i][j-1] to sum all combinations``            ``# that pin the remaining j-1's. But there is a way, when "j-f-1> = 0" we would be adding``            ``# extra combinations, so we remove the combinations that only pin the extrapolated dice face and``            ``# subtract the extrapolated combinations.``            ``mem[i][j] ``=` `mem[i][j ``-` `1``] ``+` `mem[i ``-` `1``][j ``-` `1``]``            ``if` `j ``-` `f ``-` `1` `>``=` `0``:``                ``mem[i][j] ``-``=` `mem[i ``-` `1``][j ``-` `f ``-` `1``]``    ``return` `mem[d][s]`` ` `# Driver code`` ` `print``(findWays(``4``, ``2``, ``1``))``print``(findWays(``2``, ``2``, ``3``))``print``(findWays(``6``, ``3``, ``8``))``print``(findWays(``4``, ``2``, ``5``))``print``(findWays(``4``, ``3``, ``5``))`` ` `# This code is contributed by ankush_953`

## C#

 `// C# program``// The main function that returns number of ways to get sum 'x'``// with 'n' dice and 'm' with m faces.``using` `System;`` ` `class` `GFG ``{``     ` `    ``/**``    ``* Count ways``    ``* ``    ``* @param f``    ``* @param d``    ``* @param s``    ``* @return``    ``*/``    ``public` `static` `long` `findWays(``int` `f, ``int` `d, ``int` `s) ``    ``{``        ``// Create a table to store results of subproblems. One extra ``        ``// row and column are used for simpilicity (Number of dice``        ``// is directly used as row index and sum is directly used``        ``// as column index). The entries in 0th row and 0th column``        ``// are never used.``        ``long` `[,]mem = ``new` `long``[d + 1,s + 1];``         ` `        ``// Table entries for no dices``        ``// If you do not have any data, then the value must be 0, so the result is 1``        ``mem[0,0] = 1;``        ``// Iterate over dices``        ``for``(``int` `i = 1; i <= d; i++)``        ``{``            ``// Iterate over sum``            ``for``(``int` `j = i; j <= s; j++) ``            ``{``                ``// The result is obtained in two ways, pin the current dice and spending 1 of the value, ``                ``// so we have mem[i-1,j-1] remaining combinations, to find the remaining combinations we ``                ``// would have to pin the values ??above 1 then we use mem[i,j-1] to sum all combinations ``                ``// that pin the remaining j-1's. But there is a way, when "j-f-1> = 0" we would be adding ``                ``// extra combinations, so we remove the combinations that only pin the extrapolated dice face and ``                ``// subtract the extrapolated combinations.``                ``mem[i,j] = mem[i,j-1] + mem[i-1,j-1];``                ``if``(j-f-1 >= 0)``                    ``mem[i,j] -= mem[i-1,j-f-1];``            ``}``        ``}``        ``return` `mem[d,s];``    ``}``     ` `    ``// Driver code``    ``public` `static` `void` `Main(String[] args) ``    ``{``        ``Console.WriteLine(findWays(4, 2, 1));``        ``Console.WriteLine(findWays(2, 2, 3));``        ``Console.WriteLine(findWays(6, 3, 8));``        ``Console.WriteLine(findWays(4, 2, 5));``        ``Console.WriteLine(findWays(4, 3, 5));``    ``}``}`` ` `// This code is contributed by 29AjayKumar`

Output :
```0
2
21
4
6```

Time Complexity: O(n * x) where n is number of dice and x is given sum.

Exercise:
Extend the above algorithm to find the probability to get Sum > X.