2318. Number of Distinct Roll Sequences
题目描述:
You are given an integer n
. You roll a fair 6-sided dice n
times. Determine the total number of distinct sequences of rolls possible such that the following conditions are satisfied:
- The greatest common divisor of any adjacent values in the sequence is equal to
1
. - There is at least a gap of
2
rolls between equal valued rolls. More formally, if the value of theith
roll is equal to the value of thejth
roll, thenabs(i - j) > 2
.
Return the total number of distinct sequences possible. Since the answer may be very large, return it modulo 109 + 7
.
Two sequences are considered distinct if at least one element is different.
Example 1:
Input: n = 4 Output: 184 Explanation: Some of the possible sequences are (1, 2, 3, 4), (6, 1, 2, 3), (1, 2, 3, 1), etc. Some invalid sequences are (1, 2, 1, 3), (1, 2, 3, 6). (1, 2, 1, 3) is invalid since the first and third roll have an equal value and abs(1 - 3) = 2 (i and j are 1-indexed). (1, 2, 3, 6) is invalid since the greatest common divisor of 3 and 6 = 3. There are a total of 184 distinct sequences possible, so we return 184.
Example 2:
Input: n = 2 Output: 22 Explanation: Some of the possible sequences are (1, 2), (2, 1), (3, 2). Some invalid sequences are (3, 6), (2, 4) since the greatest common divisor is not equal to 1. There are a total of 22 distinct sequences possible, so we return 22.
Constraints:
1 <= n <= 10^4
解题思路:
这个题,看条件,要求相邻两个骰子的点数互质,且两个相同的面要间隔大于2个。
这两个条件一打眼应该就是用动态规划+状态机来做。
用res<p,q>来存放当前的面为p,前一个面为q的可能性的个数,假设我们已知当前面为x、前一个面为y的组合个数,那下一个面z必须要满足:(x,z)=1,和y≠z。并且res<y,z>=sum(res<x,y> for x in y.prev)。
我们只需要用一个状态机来解决每个y前一个面的点数的可能性即可。
1: [2, 3, 4, 5, 6],
2: [1, 3, 5],
3: [1, 2, 4, 5],
4: [1, 3, 5],
5: [1, 2, 3, 4, 6],
6: [1, 5]
于是:
class Solution:
def distinctSequences(self, n: int) -> int:
if n == 1: return 6
res = collections.defaultdict(int)
mod = 10 ** 9 + 7
p_next = {
1: [2, 3, 4, 5, 6],
2: [1, 3, 5],
3: [1, 2, 4, 5],
4: [1, 3, 5],
5: [1, 2, 3, 4, 6],
6: [1, 5]
}
for i in range(6):
for j in p_next[i + 1]:
res[(j, i + 1)] = 1
for i in range(2, n):
m = collections.defaultdict(int)
for j in range(6):
for k in p_next[j + 1]:
cur = 0
for l in p_next[k]:
if j + 1 != l:
cur += res[(l, k)] % mod
m[(k, j + 1)] = cur
res = m
return sum(v for k, v in res.items()) % mod
时间复杂度:O(N*6*6*6),用状态机将后面的6优化为小一些。
额外空间复杂度:O(36)