hihocoder 1482 出勤记录II 递推 15行a

描述

小Hi的算法课老师每次上课都会统计小Hi的出勤记录。迟到会被记录一个L,缺席会被记录一个A,按时上课会被记录一个O。

一学期结束,小Hi的出勤记录可以看成是一个只包含LAO的字符串,例如"OOOOLOOOLALLO……"。

如果小Hi整学期缺席不超过1次,并且没有连续3次迟到,小Hi的出勤记录就算合格。  

现在给出字符串的长度N,小Hi想知道长度为N的出勤记录中,合格的记录总共有多少种。  

例如长度为3的合格出勤记录有19种:OOO OOL OOA OLO OAO LOO AOO OLL OLA OAL LOL LOA AOL LLO LAO ALO LLA LAL ALL。

输入

一个整数N(1 <= N <= 100000)。

输出

长度为N的合格记录总数。由于结果可能很大,你只需输出结果模109+7的余数。

样例输入

3

样例输出

19

这题用递推就可以做。

设g(i)表示长为i的合格记录的种数

设f(i)表示长为i的字符串没有A且合格记录的种树

设字符串长度为i,

若字符串最后一位是A,方案数有f(i-1)种方案。

若字符串最后两位是AL,方案数有f(i-2)种方案。

若字符串最后两位是ALL,方案数有f(i-3)种方案。

若字符串最后一位是O,方案数有g(i-1)种方案。

(上面没有考虑AO,AOO这样的情况,因为这两种情

况包含在最后一位是O的这种情况里面)

若最后两位是OL,有g(i-2)种方案,最后两位是OLL,有g(i-3)种情况。

于是得到式子:g(i)  =  f(i-1) + f(i-2) + f(i-3) + g(i-1) + g(i-2) + g(i-3);

同理,根据最后一位是O,OL,OLL这三种情况,得出f(i) = f(i-1) + f(i-2) + f(i-3);

于是g(i) = f(i) + g(i-1)+g(i-2)+g(i-3);

初始情况是f0=1,f1=2,f2=4 ,g0=1,g1=3,g2=8。

因为f3 = f1 + f2 + f0,(OLL是长度为3的一种情况,所以f0初始化为1,同理g0=1)

ac代码很短,只要十五行

#include<iostream>
using namespace std;
typedef long long ll;
const int maxn = 100010,mod = 1000000007;
ll f[maxn]={1,2,4,7},g[maxn]={1,3,8,18};
int main(){
    for(int i=3;i<=maxn;i++){
        f[i] = (f[i-1]+f[i-2]+f[i-3]) % mod;
        g[i] = (f[i]+g[i-1]+g[i-2]+g[i-3]) % mod;
    }
    int n;
    cin>>n;
    cout<<g[n]<<endl;
    return 0;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值