2020牛客竞赛 DP F 碎碎念

作者:儒生雄才1
链接:https://ac.nowcoder.com/discuss/366644
来源:牛客网

题目连接:https://ac.nowcoder.com/acm/contest/3006/F

考虑到了第iii句话时候,这种状态可能由两种状态转移而来。

  1. 直接一发AC,从第i−1i-1i1句话直接到达第iii句。
  2. 如果i>=ki>=ki>=k,可以由一发RJ从i−ki-kik句到达第i句。 构造DP[i][0/1]DP[i][0/1]DP[i][0/1],DP[i][0]DP[i][0]DP[i][0]表示到了第iii句话,是从i−1i-1i1句话AC到达的方案数。DP[i][1]DP[i][1]DP[i][1]表示到了第i句话,是由i−ki-kik句话RJ过来的方案数。 由此可知转移条件
    • DP[i][0]=DP[i−1][0]+DP[i−1][1]DP[i][0]=DP[i-1][0]+DP[i-1][1]DP[i][0]=DP[i1][0]+DP[i1][1] (前面一发是WA是AC无关紧要)
    • DP[i][1]=DP[i−k][0]DP[i][1]=DP[i-k][0]DP[i][1]=DP[ik][0] (i>=ki>=ki>=k) (前面一发只能是AC)

易确定边界条件 DP[0][0]=1DP[0][0]=1DP[0][0]=1; DP[0][1]=0DP[0][1]=0DP[0][1]=0;

由于有QQQ次查询 ,查询数目较多,我们可以线性时间内预处理前nnn项和即前缀和,然后用第RRR项减去第L−1L-1L1项即可。

 1 #include <bits/stdc++.h>
 2 #define MAXN 100005
 3 const int P = 1e9+7;
 4 using namespace std;
 5 typedef long long ll;
 6 int dp[MAXN][4]={0};
 7 int l,r;
 8 int main() {
 9     int q,k;
10     scanf("%d%d",&k,&q);
11     dp[0][0]=1;
12     for(int i=1;i<MAXN;i++){
13         dp[i][0]=(dp[i-1][0]+dp[i-1][1])%P;
14         if(i>=k){
15             dp[i][1]=dp[i-k][0];
16         }
17     }
18     dp[0][3]=1;
19     for(int i=1;i<MAXN;i++){
20         dp[i][3]=((dp[i][0]+dp[i][1])%P+dp[i][2])%P;
21 //        printf("%d ",dp[i][3]);
22         dp[i][3]+=dp[i-1][3];
23         dp[i][3]%=P;
24     }
25 
26     for(int i=0;i<q;i++){
27         scanf("%d%d",&l,&r);
28         ll ans=dp[r][3]-dp[l-1][3];
29         printf("%lld\n",((ans%P+P)%P));
30     }
31     return 0;
32 }

猜你喜欢

转载自www.cnblogs.com/pangbi/p/12307080.html