Number of Dice Rolls With Target Sum

Updated on 09 July, 2025
Number of Dice Rolls With Target Sum header image

Problem Statement

Consider a scenario where you are given n identical dice, and each die possesses k faces, which are numbered from 1 through k. You are tasked with rolling all n dice simultaneously. Your challenge is to determine the number of different ways you can achieve a specified sum, target, with the face-up numbers of all the dice. Given the massive range of combinations when rolling multiple dice (specifically kn total ways), the task becomes computationally intense. To manage large numbers, any result you derive from your calculations should be taken modulo 10^9 + 7 to ensure the numbers remain manageable and to prevent overflow.

Examples

Example 1

Input:

n = 1, k = 6, target = 3

Output:

1

Explanation:

You throw one die with 6 faces.
There is only one way to get a sum of 3.

Example 2

Input:

n = 2, k = 6, target = 7

Output:

6

Explanation:

You throw two dice, each with 6 faces.
There are 6 ways to get a sum of 7: 1+6, 2+5, 3+4, 4+3, 5+2, 6+1.

Example 3

Input:

n = 30, k = 30, target = 500

Output:

222616187

Explanation:

The answer must be returned modulo 109 + 7.

Constraints

  • 1 <= n, k <= 30
  • 1 <= target <= 1000

Approach and Intuition

In this problem, we are dealing with a combinatorial counting challenge leveraging dynamic programming for optimization due to its overlap in subproblems and optimal substructure properties. The key intuition here revolves around considering the addition of each die one at a time and determining how each added die can contribute to achieving the desired target sum:

Example Explorations:

  • Example 1:

    • Input: n = 1, k = 6, target = 3
    • The explanation is straightforward: there's only one die with six faces. To achieve the sum of 3, we just need the face showing 3, which is one way.
  • Example 2:

    • Input: n = 2, k = 6, target = 7
    • Here, the problem scales slightly: two dice and a target sum of 7. The combinations of face values to achieve 7 are (1+6, 2+5, 3+4, 4+3, 5+2, 6+1). Each pair sums to 7, yielding six ways.
  • Example 3:

    • Input: n = 30, k = 30, target = 500
    • This represents a large scale scenario with the maximum values for n and k. The result must be modularized by 10^9 + 7 not only to handle the computational limitations but also to fit into standard constraints of programming environments regarding number size.

General Strategy via Dynamic Programming:

  1. Use a table dp[i][j] where i represents the number of dice considered so far, and j represents the target sum we aim to achieve with these i dice.
  2. Initialize the table where dp[0][0] is 1 (one way to sum up to zero with zero dice), and all other dp[0][j] for j > 0 are 0 (no way to achieve positive sum with zero dice).
  3. Process each die one by one, updating ways to achieve each possible sum up to the target:
    1. For each die from 1 to n, take each target sum possibility from 0 to target.
    2. For the current die, consider adding all possible face values from 1 to k and update the DP table accordingly.

The approach is designed to methodically build up the solution by progressively adding one die after another and aggregating the ways to achieve various sums, which ensures that calculating the count for larger numbers of dice and bigger targets becomes feasible.

Solutions

  • C++
cpp
class Solution {
public:
    const int MODULO = 1000000007;
        
    int diceRollSum(int diceCount, int faceCount, int desiredSum) {
        vector<vector<int>> dp(diceCount + 1, vector<int>(desiredSum + 1, 0));
        dp[diceCount][desiredSum] = 1;
            
        for (int dice = diceCount - 1; dice >= 0; dice--) {
            for (int sumSoFar = 0; sumSoFar <= desiredSum; sumSoFar++) {
               int countWays = 0;
                    
                for (int faceValue = 1; faceValue <= min(faceCount, desiredSum - sumSoFar); faceValue++) {
                    countWays = (countWays + dp[dice + 1][sumSoFar + faceValue]) % MODULO;
                }
                    
                dp[dice][sumSoFar] = countWays;
            }
        }
            
        return dp[0][0];
    }
};

This C++ solution addresses the problem of computing the number of distinct ways to roll a certain number of dice such that their sum equals a target value. Here, the function diceRollSum takes three parameters: diceCount, faceCount, and desiredSum. The method uses dynamic programming for efficient calculation.

  • Initialize a 2D vector dp where dp[i][j] represents the number of ways to achieve a sum of j using the first i dice.

  • Set dp[diceCount][desiredSum] to 1, indicating that there is exactly one way to reach the desiredSum with exactly diceCount dice: by each die showing a value that collectively adds up to desiredSum.

  • Traverse from the last dice to the first in a nested loop structure. Loop through each possible sum thus far (sumSoFar), and calculate the number of ways to reach this sum using dice up to the current one (dice).

  • Another nested loop examines each possible face value of a dice up to the minimum between the dice's maximum face (faceCount) and the remaining sum needed to reach the desired sum (desiredSum - sumSoFar).

  • Calculate countWays by summing up all possible ways to achieve the required sumSoFar+faceValue with the remaining dice.

  • Update each state in dp[dice][sumSoFar] by setting it to countWays.

  • Use modulo operation with MODULO (10^9 + 7) to prevent integer overflow and maintain the results within the specified limit.

The final result, dp[0][0], gives the number of ways to obtain the desiredSum from all diceCount dice, starting from a sum of zero. This approach ensures that calculations are manageable and efficient by leveraging the overlapping subproblems using dynamic programming.

  • Java
java
class Solver {
    final int MODULO = 1000000007;
    
    public int calculateNumberOfWays(int dice, int faces, int sum) {
        int[][] dp = new int[dice + 1][sum + 1];
        dp[dice][sum] = 1;
    
        for (int idx = dice - 1; idx >= 0; idx--) {
            for (int currentSum = 0; currentSum <= sum; currentSum++) {
                int countWays = 0;
    
                for (int faceValue = 1; faceValue <= Math.min(faces, sum - currentSum); faceValue++) {
                    countWays = (countWays + dp[idx + 1][currentSum + faceValue]) % MODULO;
                }
    
                dp[idx][currentSum] = countWays;
            }
        }
    
        return dp[0][0];
    }
}

In the solution presented, you achieve the goal of calculating the number of ways to roll a set of dice to achieve a specific target sum. This approach utilizes dynamic programming to efficiently solve the problem using a Java method named calculateNumberOfWays inside the Solver class. Here's a breakdown of how this method functions:

  • Initialization: An array dp is initialized with (dice + 1) rows and (sum + 1) columns, filled with zeros. It utilizes dynamic programming to store intermediate results, where dp[i][j] represents the number of ways to obtain a sum j using the first i dices.

  • Base Case Setting: The code sets dp[dice][sum] to 1, establishing the base case that there is exactly one way to achieve the target sum using all the dice if that exact sum is reached.

  • Iterative Computation:

    • Loop through each die from the last one to the first (for loop moving backwards).
    • For every possible sum from 0 to the target sum, compute the number of ways the sum can be gathered.
    • A nested loop then iterates over all possible face values that each die can show. It adds up ways from subsequent states, making sure not to exceed the number of available faces or the sum decrementing as necessary for the recursion.
    • The modulo operation ensures that the results are within manageable numeric limits, preventing integer overflow.
  • Final Return: After populating the dp array, dp[0][0] gives the total number of ways to achieve the target sum with the given number of dice. This outcome represents the solution to the problem.

This dynamic programming solution effectively reduces the complexity of the problem from exponential in nature, typical with recursive approaches, to polynomial with respect to the number of dice and the target sum. This ensures the method is efficient and scales well with larger inputs.

Comments

No comments yet.