碎碎念
https://ac.nowcoder.com/acm/contest/3006/F
本题涉及动态规划
针对第i次喊叫,有AC和RJ两种情况,分别用DP[i][0]和DP[i][1]表示
可划分为两种情况
i<x时候,只能是AC,DP[i][0]=DP[i-1]0此时DP[i-1][1]是0
i>=x时,分两种情况:
1:第i次是AC,则DP[i][0]=DP[i-1][0]+DP[i-1][1]
2:第i次是RJ,则DP[i][1]=DP[i-x][0] (RJ前一次必定是AC)
临界条件:DP[0][0]=1,DP[0][1]=0;
DP[0][0]=1,DP[0][1]=0;
for (int i = 1; i < N; i++) {
DP[i][0] = (DP[i - 1][0] + DP[i - 1][1]) % mod;
if (i >= x) {
DP[i][1] = DP[i - x][0];
}
}有Q次询问,可考虑前缀和记录总方案数
DP[i][2] = (DP[i][0] + DP[i][1]) % mod; DP[i][2] += DP[i - 1][2]; DP[i][2] %= mod;
代码如下
#pragma warning (disable :4996)
#include <iostream>
#include <cstdio>
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
const double eps = 1e-7;
const int N = 1e5 + 10;
int x, Q;
ll DP[N][4];
int main() {
scanf("%d", &x);
DP[0][0] = 1;
for (int i = 1; i < N; i++) {
DP[i][0] = (DP[i - 1][0] + DP[i - 1][1]) % mod;
if (i >= x) {
DP[i][1] = DP[i - x][0];
}
DP[i][2] = (DP[i][0] + DP[i][1]) % mod;
DP[i][2] += DP[i - 1][2];
DP[i][2] %= mod;
}
scanf("%d", &Q);
while (Q--) {
int le, r;
scanf("%d %d", &le, &r);
ll ans = (DP[r][2] - DP[le - 1][2] + mod) % mod;
cout << ans<< endl;
}
}


京公网安备 11010502036488号