牛客寒假5-F碎碎念| dp + 前缀和

题目地址:https://ac.nowcoder.com/acm/contest/3006/F

思路

1.区间查询,想到前缀和,所以主要就是计算喊i声时的方案数

2-1思路1:考虑递推关系
一维递推关系
假设前i-1声已经算过,那么第i声时方案数怎么计算?
容易想到👇
第i声方案数 = 第i-1声AC方案数(这一次ac) + 第i-x声方案数(这一次wa,i-x~x内算在这一次wa时的贡献里)
dp[i] = dp[i-1] + dp[i-x-1]

3.初始化边界
dp[i] = 1;
dp[x] = 2;

思路2:二维递推

初始化边界:dp[i][0] = 1;第i声是AC的方案数 = 1;

4.计算前缀和,区间查询 sum(r) - sum(l-1)即为[l,r]的方案数

AC代码

思路1

转载

思路2

#include <bits/stdc++.h>
#define maxn 200005
typedef long long ll;
const ll mod = 1e9 + 7;
using namespace std;
int N, M, K;
ll dp[maxn][2];	
ll f[maxn];
int main(){
	int x;
	cin >> x;dp[x][1] = 1;
	for (int i = 1; i <= x; i++)
		dp[i][0] = 1;
	for (int i = x + 1; i <= 100000; i++) {
		dp[i][0] = (dp[i - 1][0] + dp[i - 1][1])%mod; //ac
		dp[i][1] = (dp[i][1] + dp[i - x][0])%mod; //wa
	}
	for (int i = 1; i <= 100000; i++)
		f[i] = (dp[i][0] + dp[i][1] + f[i - 1]) % mod; //前缀和 
	int t;
	cin>>t;
	while (t--) {
		int l, r;
		cin>>l>>r;
		cout<<(f[r] - f[l - 1] + mod) % mod <<endl;
	}
	return 0;
}

posted @ 2020-02-16 14:20  fishers  阅读(131)  评论(0编辑  收藏  举报