牛客网暑期ACM多校训练营(第二场)A-RUN

牛客网暑期ACM多校训练营(第二场)A-RUN

题目描述 

White Cloud is exercising in the playground.
White Cloud can walk 1 meters or run k meters per second.
Since White Cloud is tired,it can't run for two or more continuous seconds.
White Cloud will move L to R meters. It wants to know how many different ways there are to achieve its goal.
Two ways are different if and only if they move different meters or spend different seconds or in one second, one of them walks and the other runs.

输入描述:

The first line of input contains 2 integers Q and k.Q is the number of queries.(Q<=100000,2<=k<=100000)
For the next Q lines,each line contains two integers L and R.(1<=L<=R<=100000)

输出描述:

For each query,print a line which contains an integer,denoting the answer of the query modulo 1000000007.

示例1

输入

3 3

3 3

1 4

1 5

输出

2

7

11

比赛完了之后,与其他同学交流后,他们说我这个想法还是比较好的。那就分享一下吧。

题意:在一条直线上,给定L到R这个区间,你从0开始跑步或者走路,跑步就是移动K步,走路是移动1步。问你从0到[L,R]这个区间有多少种方式,模1e9+7。不可以连着跑。例如 样例 3 3 可以走三步,或者跑一步。俩种方式。

这道题我采取的是DP的方法,不同于出题人所给题解的二维数组的DP,我用的是一维数组进行的DP

分析:在说明这道题目之前,我们回忆一下之前的上楼梯问题,一次可以上2楼一次可以上1楼,当我们位于比楼层数大于等于3的时候,我们看成当前的楼层数由下一楼层走一步,和下俩层楼层走俩步而得到。

那么也就是说 dp[n]=dp[n-1]+dp[n-2];(n>=3)

这道题目也是同理,K步之前只能走。我们走到K步以后,可以看成由前K步以前跑步过来和前一步走一步过来。

也就是 dp[n]=dp[n-k]+dp[n-1]  但是这道题有一个地方,就是不可以连续跑步。也就是说dp[n-k]中存在最后一步就是跑步的情况,再跑K步是一个不合法的操作。

虽然式子错了,但是思想没有问题。我们虽然不可以由do[n-k]直接跑过来。但是,我们可以由dp[n-k-1]也就是说由n-k-1走一步再跑一步过来!!!这样就会让跑步和跑步分开!

所以我们得到本题的DP式:dp[n]=dp[n-1]+d[n-k-1]

关键式子求出来了,其余的各种姿势(做法)都可以采取了。这里我采取的是这样的预处理。

这道题对于一群查询K都是固定的。也就是说。我们可以先预处理出来1到100000的每一步的次数。因为是区间查询,我们把他们一次累加。使DP[n]即为1到n的和。这样将输入的L R读入。直接输出dp[r]-dp[l-1]即可。

AC代码如下:

#include<bits/stdc++.h>
using namespace std;
#define mod 1000000007
int q,k;
int l,r;
long long int dp[100005];
int main ()
{
    scanf("%d%d",&q,&k);
    for(int i=1;i<k;i++)
    {
        dp[i]=1;
    }
    dp[k]=2;
    dp[k+1]=3;
    for(int i=k+2;i<=100001;i++)
    {
        dp[i]=(dp[i-1]+dp[i-k-1])%mod;
    }
    for(int i=2;i<=100001;i++)
    {
        dp[i]=dp[i-1]%mod+dp[i]%mod;
    }
    for(int i=0;i<q;i++)
    {
        scanf("%d%d",&l,&r);
        long long int ans=(dp[r]-dp[l-1])%mod;
        printf("%lld\n",ans);
    }
    return 0;
}

有什么建议或者问题,欢迎私信博主。欢迎讨论。

转载请注明出处!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值