2020牛客寒假算法基础集训营5 F 碎碎念

https://ac.nowcoder.com/acm/contest/3006/F

题目描述

在ACM比赛里,除了CE以外都是有效的提交。每一个提交都会有其评测的结果,或是AC,或是RJ(Rejected,包含各种不通过的情况)。往往一个人上去提交的时候,总有一个队友会坐在边上等着结果。那个人,往往都是只读题不写题的云选手~

牛牛战队里也有这样的云选手——牛能。当牛能看到有效提交得到了AC以后,都会大呼一声“你好能啊!”,反之,如果得到了RJ的话,就会化身为喷子,说xxx句“你能不能行啊!”。大家比赛的都十分紧张,这样的大声呼喊未免会引起旁边队伍的注意。

当然牛牛战队交题的时候也很小心,一旦这一发出现了RJ,下一发有效提交一定能获得AC。

比赛结束了以后,旁边的一支队伍愤怒的跑过来说:你们比赛的时候吵不吵啊,一直在这大吼,吼了这么多句!

激烈的争吵引起了吃瓜群众的注意,吃瓜群众问道:吼了多少句啊,这么讨厌的吗

“啊……我也记不清了,大概是在[L,R]这个区间吧”

作为吃瓜群众的你,想根据这个信息算出,这个队伍有多少种有效提交结果序列的可能呢?

思路

很简单一个dp而已,可惜我没看到上面红色标记那句话,疯狂WA

f[i][0]表示前面说了i句话,并且最后一次AC了,f[i][1]就是前面说了i句话并且最后一发RJ了

考虑状态转移吧

  • f[i][0]容易一点,就是前面i-1句话最后一个不论结果,所以是f[i-1][0]+f[i-1][1]
  • f[i][1]也不复杂,就是需要用上面红色的那句话,如果前面那个状态的最后结果是RJ,当前这个RJ就不会是它的下一个状态,因此只有f[i - k][0]

这就求出来说了每句话的方案数了,然后求一个前缀和,查询区间[L,R]时,sum[R]-sum[L-1]就是结果,减法注意是负数,加个mod再取模即可

/*************************************************************************
    > File Name: F.cpp
    > Author: amoscykl
    > Mail: amoscykl@163.com
    > Created Time: 2020年02月14日 星期五 18时24分54秒
 ************************************************************************/
 
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int q, n, x;
#define mem(a, b) memset(a, b, sizeof a)
typedef long long ll;
ll f[N][4];
const int mod = 1e9 + 7;
int main()
{
    ios::sync_with_stdio(0);
    cin >> x;
    mem(f, 0);
    // f[i][0] 说了i句话,并且最后一次ac
    // f[i][1] 说了i句话,并且最后一次rj
    // 注意:rj之后必定ac
    f[0][0] = 1;
    f[0][1] = 0;
    f[0][2] = 1;
    for (int i = 1; i <= 100000; i++){
        f[i][0] = (f[i - 1][0] + f[i - 1][1]) % mod;
        if (i >= x){
            f[i][1] = f[i - x][0];
            f[i][1] %= mod;
        }
    }
    for (int i = 1; i <= 100000; i++){
        f[i][2] = (f[i - 1][2] + f[i][1] + f[i][0]) % mod;
    }
    cin >> q;
    while (q--){
        int l, r;
        cin >> l >> r;
        ll res = f[r][2] - f[l - 1][2];
        res = (res + mod) % mod;
        cout << res << "\n";
    }
    return 0;
}

 

评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值