dp+区间查询(前缀和) 7.21牛客暑期多校训练营二 A

  1. 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

题目大意:

​ 一秒内能走1米,跑K米,不能连续跑2秒以上,问到达[L,R]范围内有几种方案

想法:

题意刚开始没读懂。原来是L~R,不是从L到R,即要求得是前缀和,再减成区间。

很明显的DP,签到题吧

思路:

1、dp。可以根据i前面的结果求出到达i米的方案数,无后效性。当前状态方案数=前一秒是走状态走过来+前一秒是跑状态走过来+前一秒是走状态跑过来

dp[i][0]=dp[i-1][1]+dp[i-1][0] dp[i][1] = dp[i-1][0]

2、维护前缀和。sum[i] = sum[i-1] + dp[i][1] + dp[i][0]

3、查询区间结果,即sum[r] - sum[l-1]

4、注意前k米是没有前状态为跑的,i<k,dp[i][1]=0

5、注意取模

AC代码:

因为之前循环条件越界,WA了2个小时,可怜曦哥

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int mod = 1000000007;
int main(){
    int k, q;
    int sum[100005], dp[100005][2];
     
    cin>>q>>k;
     
    memset(sum, 0, sizeof(sum));
    memset(dp, 0, sizeof(dp));
     
    dp[0][0] = 1;
    for (int i = 1; i <= 100003; i++) {
        dp[i][0] = (dp[i-1][1] + dp[i-1][0]) % mod;
        if(i >= k) {
            dp[i][1] = dp[i-k][0];
        }
        sum[i] = (sum[i-1] + dp[i][1] + dp[i][0]) % mod;
    }
     
    int l, r;
    while(q--) {
        cin>>l>>r;
        cout<<(sum[r] - sum[l-1] + mod) % mod<<endl;   
    }
    return 0;
}

​ 可以再深入想想,dp[i]选择走的方案数=dp[i-1]的方案数,所以dp[j]选择跑而不是连续跑的方案数=dp[i-k-1]的方案数。所以就不用上面代码中的考虑表示选择跑、走的二维数组,用一维数组就可以了

看刘老板代码想到的。。。

#include <iostream>
#include <cstring>
using  namespace std;
typedef long long LL;
LL dp[100005];
LL sum[100005];
LL mod = 1000000007;
int main(){
    LL q,k, l, r;
    memset(dp, 0 ,sizeof(dp));
    memset(sum, 0, sizeof(sum));
    cin >> q >> k;
    for(int i=0;i<k;i++){
        dp[i]=1;
    }
    for(int i=k + 1;i<100005;i++){
        dp[i]=dp[i-1]+dp[i-k-1];
        dp[i]%=1000000007;
    }
        
    for(int i=1;i<10;i++){
        cout << dp[i] << ' ';
    }
    cout << endl;
​
    /*
    for(int i = 1 ; i <= 100; ++i){
        cout << dp[i][0] << ' ' << dp[i][1] << endl;
    }
    for(int i = 1 ; i <= 10; ++i){
        cout << sum[i]  << ' ';
    }
    cout<< endl;
​
    */  
    
    /*
     for(LL i = 0; i < q; ++i){
        cin >>l >>r;
        cout << (sum[r] - sum[l - 1] + mod) % mod<< endl;
     }
     */
     return 0;
} 

猜你喜欢

转载自blog.csdn.net/keeeepgo/article/details/81153928
今日推荐