英文原文
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 exact n rolls. Since the answer may be too large, return it modulo 109 + 7.
Two sequences are considered different if at least one element differs from each other.
Example 1:
Input: n = 2, rollMax = [1,1,2,2,2,3] Output: 34 Explanation: There will be 2 rolls of die, if there are no constraints on the die, there are 6 * 6 = 36 possible combinations. In this case, 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 is 36-2 = 34.
Example 2:
Input: n = 2, rollMax = [1,1,1,1,1,1] Output: 30
Example 3:
Input: n = 3, rollMax = [1,1,1,2,2,3] Output: 181
Constraints:
1 <= n <= 5000rollMax.length == 61 <= rollMax[i] <= 15
中文题目
有一个骰子模拟器会每次投掷的时候生成一个 1 到 6 的随机数。
不过我们在使用它时有个约束,就是使得投掷骰子时,连续 掷出数字 i 的次数不能超过 rollMax[i](i 从 1 开始编号)。
现在,给你一个整数数组 rollMax 和一个整数 n,请你来计算掷 n 次骰子可得到的不同点数序列的数量。
假如两个序列中至少存在一个元素不同,就认为这两个序列是不同的。由于答案可能很大,所以请返回 模 10^9 + 7 之后的结果。
示例 1:
输入:n = 2, rollMax = [1,1,2,2,2,3] 输出:34 解释:我们掷 2 次骰子,如果没有约束的话,共有 6 * 6 = 36 种可能的组合。但是根据 rollMax 数组,数字 1 和 2 最多连续出现一次,所以不会出现序列 (1,1) 和 (2,2)。因此,最终答案是 36-2 = 34。
示例 2:
输入:n = 2, rollMax = [1,1,1,1,1,1] 输出:30
示例 3:
输入:n = 3, rollMax = [1,1,1,2,2,3] 输出:181
提示:
1 <= n <= 5000rollMax.length == 61 <= rollMax[i] <= 15
通过代码
高赞题解
思路
用 dp[i][j][k] 表示第 i 轮掷骰子掷出数字 j 时 j 连续出现 k 次的组合数量。
那么有状态转移如下:
当 j 并非在连续出现时(即 k == 1 时):
// j 出现 1 次的组合数等于上一轮投出非数字 j 的所有情况和
dp[i][j][1] = sum(dp[i - 1][other != j][:])
当 j 连续出现 k(k > 1) 次时:
if k <= rollMax[j]:
// 本轮投出连续出现 k 次数字 j 的情况数量等于:上一轮连续投掷出 k - 1 次 j 的情况数量
dp[i][j][k] = dp[i - 1][j][k - 1]
ps:很多同学说测试用例是错的,可能是因为理解错题意了,题目说的是 连续 掷出数字 i 的次数不能超过 rollMax[i],而不是数字的投掷总数。
具体实现:
class Solution:
def dieSimulator(self, n: int, rollMax: List[int]) -> int:
dp = [[[0 for _ in range(16)] for _ in range(7)] for _ in range(n + 1)]
mod = 10**9 + 7
for i in range(1, n + 1):
# 投掷的数
for j in range(1, 7):
# 第一次投掷
if i == 1:
dp[i][j][1] = 1
continue
# 数字 j 连续出现 k 次
for k in range(2, rollMax[j - 1] + 1):
dp[i][j][k] = dp[i - 1][j][k - 1]
# 前一次投出的数不是 j
s = 0
for l in range(1, 7):
if l == j:
continue
for k in range(1, 16):
s += dp[i - 1][l][k]
s %= mod
dp[i][j][1] = s
res = 0
for j in range(1, 7):
for k in range(1, 16):
# 求投掷 n 次时所有组合总和
res += dp[n][j][k]
res %= mod
return res
🐱
统计信息
| 通过次数 | 提交次数 | AC比率 |
|---|---|---|
| 3468 | 7274 | 47.7% |
提交历史
| 提交时间 | 提交结果 | 执行时间 | 内存消耗 | 语言 |
|---|