作者:儒生雄才1
链接:https://ac.nowcoder.com/discuss/366644
来源:牛客网
题目连接:https://ac.nowcoder.com/acm/contest/3006/F
考虑到了第iii句话时候,这种状态可能由两种状态转移而来。
- 直接一发AC,从第i−1i-1i−1句话直接到达第iii句。
- 如果i>=ki>=ki>=k,可以由一发RJ从i−ki-ki−k句到达第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-1i−1句话AC到达的方案数。DP[i][1]DP[i][1]DP[i][1]表示到了第i句话,是由i−ki-ki−k句话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[i−1][0]+DP[i−1][1] (前面一发是WA是AC无关紧要)
- DP[i][1]=DP[i−k][0]DP[i][1]=DP[i-k][0]DP[i][1]=DP[i−k][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-1L−1项即可。
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 }