A die simulator generates a random number from 1 to 6 for each roll. You introduced a constraint to the generator such that it cannot roll the number i more than rollMax[i] (1-indexed) consecutive times.
Given an array of integers rollMax and an integer n, return the number of distinct sequences that can be obtained with exactnrolls. Since the answer may be too large, return it modulo109 + 7.
Two sequences are considered different if at least one element differs from each other.
Input: n =2, rollMax =[1,1,2,2,2,3]Output: 34Explanation: There will be 2 rolls of die,if there are no constraints on the die, there are 6*6=36 possible combinations. In thiscase, looking at rollMax array, the numbers 1 and 2 appear at most once consecutively, therefore sequences(1,1) and (2,2) cannot occur, so the final answer is36-2=34.
We use dynamic programming to count the number of valid sequences. The key is to track, for each roll, which number was last rolled and how many times it has appeared consecutively. By memoizing the state (rolls_left, last_num, last_count), we avoid redundant calculations.
classSolution {
public:int dieSimulator(int n, vector<int>& rollMax) {
constint MOD =1e9+7;
int dp[501][6][16] = {};
memset(dp, -1, sizeof(dp));
function<int(int, int, int)> dfs = [&](int left, int last, int cnt) ->int {
if (left ==0) return1;
if (last !=-1&& dp[left][last][cnt] !=-1) return dp[left][last][cnt];
int ans =0;
for (int i =0; i <6; ++i) {
if (i == last) {
if (cnt < rollMax[i])
ans = (ans + dfs(left -1, i, cnt +1)) % MOD;
} else {
ans = (ans + dfs(left -1, i, 1)) % MOD;
}
}
if (last !=-1) dp[left][last][cnt] = ans;
return ans;
};
returndfs(n, -1, 0);
}
};
classSolution {
publicintdieSimulator(int n, int[] rollMax) {
int MOD = 1000000007;
Integer[][][] dp =new Integer[n+1][7][16];
return dfs(n, -1, 0, rollMax, dp, MOD);
}
privateintdfs(int left, int last, int cnt, int[] rollMax, Integer[][][] dp, int MOD) {
if (left == 0) return 1;
if (last !=-1 && dp[left][last][cnt]!=null) return dp[left][last][cnt];
int ans = 0;
for (int i = 0; i < 6; i++) {
if (i == last) {
if (cnt < rollMax[i])
ans = (ans + dfs(left-1, i, cnt+1, rollMax, dp, MOD)) % MOD;
} else {
ans = (ans + dfs(left-1, i, 1, rollMax, dp, MOD)) % MOD;
}
}
if (last !=-1) dp[left][last][cnt]= ans;
return ans;
}
}
classSolution {
fundieSimulator(n: Int, rollMax: IntArray): Int {
val MOD = 1_000_000_007
val dp = Array(n+1) { Array(7) { IntArray(16) { -1 } } }
fundfs(left: Int, last: Int, cnt: Int): Int {
if (left ==0) return1if (last != -1&& dp[left][last][cnt] != -1) return dp[left][last][cnt]
var ans = 0for (i in0..5) {
if (i == last) {
if (cnt < rollMax[i])
ans = (ans + dfs(left-1, i, cnt+1)) % MOD
} else {
ans = (ans + dfs(left-1, i, 1)) % MOD
}
}
if (last != -1) dp[left][last][cnt] = ans
return ans
}
return dfs(n, -1, 0)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
classSolution:
defdieSimulator(self, n: int, rollMax: list[int]) -> int:
MOD =10**9+7from functools import lru_cache
@lru_cache(maxsize=None)
defdp(left: int, last: int, cnt: int) -> int:
if left ==0:
return1 ans =0for i in range(6):
if i == last:
if cnt < rollMax[i]:
ans = (ans + dp(left-1, i, cnt+1)) % MOD
else:
ans = (ans + dp(left-1, i, 1)) % MOD
return ans
return dp(n, -1, 0)
We use bottom-up dynamic programming to build the solution iteratively. Instead of recursion, we fill a DP table where each entry represents the number of ways to reach a certain state (rolls left, last number, consecutive count). This avoids stack overhead and is often more efficient.
classSolution:
defdieSimulator(self, n: int, rollMax: list[int]) -> int:
MOD =10**9+7 dp: list[list[list[int]]] = [[[0]*16for _ in range(6)] for _ in range(n+1)]
for f in range(6):
dp[1][f][1] =1for r in range(2, n+1):
for f in range(6):
for pf in range(6):
if pf == f:
continuefor cnt in range(1, rollMax[pf]+1):
dp[r][f][1] = (dp[r][f][1] + dp[r-1][pf][cnt]) % MOD
for cnt in range(2, rollMax[f]+1):
dp[r][f][cnt] = (dp[r][f][cnt] + dp[r-1][f][cnt-1]) % MOD
ans =0for f in range(6):
for cnt in range(1, rollMax[f]+1):
ans = (ans + dp[n][f][cnt]) % MOD
return ans
impl Solution {
pubfndie_simulator(n: i32, roll_max: Vec<i32>) -> i32 {
constMOD: i32=1_000_000_007;
let n = n asusize;
letmut dp =vec![vec![vec![0; 16]; 6]; n+1];
for f in0..6 {
dp[1][f][1] =1;
}
for r in2..=n {
for f in0..6 {
for pf in0..6 {
if pf == f { continue; }
for cnt in1..=roll_max[pf] asusize {
dp[r][f][1] = (dp[r][f][1] + dp[r-1][pf][cnt]) %MOD;
}
}
for cnt in2..=roll_max[f] asusize {
dp[r][f][cnt] = (dp[r][f][cnt] + dp[r-1][f][cnt-1]) %MOD;
}
}
}
letmut ans =0;
for f in0..6 {
for cnt in1..=roll_max[f] asusize {
ans = (ans + dp[n][f][cnt]) %MOD;
}
}
ans
}
}