牛客3006F-碎碎念-dp+前缀和

链接:https://ac.nowcoder.com/acm/contest/3006/F
来源:牛客网

题目描述:

在ACM比赛里,除了CE以外都是有效的提交。每一个提交都会有其评测的结果,或是AC,或是RJ(Rejected,包含各种不通过的情况)。往往一个人上去提交的时候,总有一个队友会坐在边上等着结果。那个人,往往都是只读题不写题的云选手~
牛牛战队里也有这样的云选手——牛能。当牛能看到有效提交得到了AC以后,都会大呼一声“你好能啊!”,反之,如果得到了RJ的话,就会化身为喷子,说xxx句“你能不能行啊!”。大家比赛的都十分紧张,这样的大声呼喊未免会引起旁边队伍的注意。
当然牛牛战队交题的时候也很小心,一旦这一发出现了RJ,下一发有效提交一定能获得AC。
比赛结束了以后,旁边的一支队伍愤怒的跑过来说:你们比赛的时候吵不吵啊,一直在这大吼,吼了这么多句!
激烈的争吵引起了吃瓜群众的注意,吃瓜群众问道:吼了多少句啊,这么讨厌的吗
“啊……我也记不清了,大概是在[L,R][L,R][L,R]这个区间吧”
作为吃瓜群众的你,想根据这个信息算出,这个队伍有多少种有效提交结果序列的可能呢?

输入描述:

输入数据包括单组数据、多组询问。输入第一行包含一个整数x(2≤x≤100 000),表示牛能在RJ状态下会说“你能不能行啊!”的句子数量。
第二行包括一个整数Q(1≤Q≤105),表示询问数量。
接下来Q行,每行包括两个整数L,R(1≤L≤R≤100 000),表示每次询问下句子的区间数。

输出描述:

对于每组数据,在一行内输出一个整数,表示牛牛战队提交结果的可能性。由于结果可能很大,请对1 000 000 007取模。

输入样例:

3
3
3 3
1 4
1 5

输出样例:

2
7
11

核心思想:

动态规划。
dp[i][0]表示共说了i句话,并且最后一发RJ了;
dp[i][1]表示共说了i句话,并且最后一发AC了。
状态转移:
dp[i][1]=dp[i-1][0]+dp[i-1][1]
dp[i][0]=dp[i-x][1]

有Q次区间查询,预处理成前缀和sum[i]。
查询区间[l,r]时,输出sum[r]-sum[l-1]即可。

注意取模,详见代码。

代码如下:

#include<cstdio>
#include<iostream>
using namespace std;
typedef long long ll;
const int N=1e5+20;
const ll mo=1e9+7;
int dp[N][2],sum[N];
int main()
{
	int x,q,l,r;
	cin>>x>>q;
	for(int i=1;i<x;i++)
	{
		dp[i][1]=1;
		dp[i][0]=0;
	}
	dp[x][1]=dp[x][0]=1;
	for(int i=x+1;i<N;i++)
	{
		dp[i][1]=(dp[i-1][0]+dp[i-1][1])%mo;
		dp[i][0]=dp[i-x][1];
	}
	for(int i=1;i<N;i++)
		sum[i]=(sum[i-1]+(dp[i][0]+dp[i][1])%mo)%mo;
	while(q--)
	{
		scanf("%d%d",&l,&r);
		printf("%d\n",(sum[r]+mo-sum[l-1])%mo);
	}
	return 0;
}
发布了144 篇原创文章 · 获赞 135 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Nothing_but_Fight/article/details/104301573
今日推荐