leetcode 552. 学生出勤记录 II

可以用字符串表示一个学生的出勤记录,其中的每个字符用来标记当天的出勤情况(缺勤、迟到、到场)。记录中只含下面三种字符:

        "A": Absent,缺勤

        "L": Late,迟到

        "P": Present,到场

如果学生能够同时满足下面两个条件,则可以获得出勤奖励:

        1、按总出勤计,学生缺勤("A")严格少于两天。

        2、学生不会存在连续3天或连续3天以上的迟到("L")记录。

给你一个整数n,表示出勤记录的长度(次数)。请你返回记录长度为n时,可能获得出勤奖励的记录情况数量。答案可能很大(你忍一下),所以返回对10^9 + 7取余的结果。

解:怎么说,感觉有点类似10年数学省赛二试最后一题

以下用T(n)表示可获得出勤奖励的记录情况数量,a(n),b(n),c(n),d(n),e(n),f(n)表示各种可获得出勤奖励的记录情况数量,映射关系如下表所示(其中列表示记录中"A"的数量,行表示记录结尾"L"的数量),不难看出T(n) = a(n) + b(n) + c(n) + d(n) + e(n) + f(n)

012
0abc
1def

不难得知,对于T(n + 1)的所有可能情况等同于在T(n)末尾添加一个字符后仍满足要求的情况,因此,对a,b,c,d,e,f添加一个字符的情况依次进行考虑(纯体力活):

ALP
adab
bdac
cda/
d/de
e/df
f/d/

因此有下列递归关系:

        T(n) = a(n) + b(n) + c(n) + d(n) + e(n) + f(n)

        a(n + 1) = a(n) + b(n) + c(n)

        b(n + 1) = a(n)

        c(n + 1) = b(n)

        d(n + 1) = a(n) + b(n) + c(n) + d(n) + e(n) + f(n)

        e(n + 1) = d(n)

        f(n + 1) = e(n)

推出:t(n) = a(n) + a(n - 1) + a(n - 2) + t(n - 1) + t(n - 2) + t(n - 3)

t(1) = 3,t(2) = 8,t(3) = 19

a(1) = 1,a(2) = 2,a(3) = 4

于是有

class Solution:
    def checkRecord(self, n: int) -> int:
        a1 = 1
        a2 = 2
        a3 = 4
        t1 = 3
        t2 = 8
        t3 = 19
        if n == 1:
            return t1
        elif n == 2:
            return t2
        elif n == 3:
            return t3
        else:
            while n - 3 > 0:
                a1, a2, a3 = a2, a3, a1 + a2 + a3
                t1, t2, t3 = t2, t3, a1 + a2 + a3 + t1 + t2 + t3
                n -= 1
            return t3 % (10**9 + 7)

if __name__ == '__main__':
    s = Solution()
    s.checkRecord(10101) # print(183236316)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值