An attendance record for a student can be represented as a string where each character signifies whether the student was absent, late, or present on that day. The record only contains the following three characters:
‘A’: Absent.
‘L’: Late.
‘P’: Present.
Any student is eligible for an attendance award if they meet both of the following criteria:
The student was absent (‘A’) for strictly fewer than 2 days total.
The student was never late (‘L’) for 3 or more consecutive days.
Given an integer n, return the number of possible attendance records of length n that make a student eligible for an attendance award. The answer may be very large, so return it modulo 109 + 7.
Example 1:
Input: n = 2
Output: 8
Explanation: There are 8 records with length 2 that are eligible for an award:
“PP”, “AP”, “PA”, “LP”, “PL”, “AL”, “LA”, “LL”
Only “AA” is not eligible because there are 2 absences (there need to be fewer than 2).
Example 2:
Input: n = 1
Output: 3
Example 3:
Input: n = 10101
Output: 183236316
Constraints:
- 1 <= n <= 105
l[i]代表第 i 天为 L 时,可以拿奖的组合数量
p[i]代表第 i 天为 P 时,可以拿奖的组合数量
a[i]代表第 i 天为 A 时,可以拿奖的组合数量
第 i 天为 L 时, 我们要想拿奖,需要保证(i-1)和(i-2)两天不能都为 L, 否则就会形成连续三天迟到不能拿奖的情况。反过来想, 只要(i-1)和(i-2)两天中的任意一天为 P 或者 A, 我们就可以继续拿奖。所以 l[i] = (i-1)为 P 的拿奖组合 + (i-1)为 A 的拿奖组合 + (i-2)为 P 的拿奖组合 + (i-2)为 A 的拿奖组合, 即 l[i] = p[i-1] + a[i-1] + p[i-2] + a[i-2]
第 i 天为 P 时, 只要 i-1 天的状态可以拿奖,我们就可以拿奖。所以, p[i] = l[i-1] + p[i-1] + a[i-1]
第 i 天为 A 时, 只要 i 之前的天里没有 A 即可以拿奖。但是现在我们想表达之前的天数里没有 A 比较困难, 所以我们要定义另外两个表达方式:
nal[i]代表第 i 天为 L 且前面所有的天数中都不存在 A 的,可以拿奖的组合数量
nap[i]代表第 i 天为 p 且前面所有的天数中都不存在 A 的,可以拿奖的组合数量
这样 a[i]就可以表达为 nal[i-1] + nap[i-1]
nap[i] = nap[i-1] + nal[i-1], 这个比较好理解
nal[i]跟我们前面分析的 l[i]相似, 只要 i-1 和 i-2 有一天不为 L 且不为 A 即可, 既不为 L 也不为 A 那就只剩下 P 了, 所以 nal[i] = nap[i-1] + nap[i-2]
最终答案是(l[n-1] + p[n-1] + a[n-1]) % 1000000007, 这也比较好理解, 分别以 L、P、A 结尾的获奖组合数的和
impl Solution {
pub fn check_record(n: i32) -> i32 {
if n == 1 {
return 3;
}
const M: i64 = 10i64.pow(9) + 7;
let mut a = vec![0; n as usize];
let mut l = vec![0; n as usize];
let mut p = vec![0; n as usize];
let mut nal = vec![0; n as usize];
let mut nap = vec![0; n as usize];
a[0] = 1;
a[1] = 2;
l[0] = 1;
l[1] = 3;
p[0] = 1;
p[1] = 3;
nal[0] = 1;
nal[1] = 2;
nap[0] = 1;
nap[1] = 2;
for i in 2..n as usize {
nap[i] = (nal[i - 1] + nap[i - 1]) % M;
nal[i] = (nap[i - 1] + nap[i - 2]) % M;
a[i] = (nap[i - 1] + nal[i - 1]) % M;
l[i] = (a[i - 1] + p[i - 1] + a[i - 2] + p[i - 2]) % M;
p[i] = (a[i - 1] + l[i - 1] + p[i - 1]) % M;
}
((a[n as usize - 1] + l[n as usize - 1] + p[n as usize - 1]) % M) as i32
}
}