题目大意:白云一次能走一个单位/跑k个单位,且不能连续跑,问白云移动距离位于[l, r]的不同方法数
由于询问组数较多,考虑预处理
设置二维数组dp[N][2],dp[i][0]表示走到数轴上i点的方法数,dp[i][1]表示跑到数轴上i点的方法数
设置一维数组ans[N],ans[i]表示移动距离落在[0,i]区间的方法数,所以在计算ans[i]时要加上ans[i-1],答案即为求前缀和:ans=ans[r]-ans[l-1]
递推方程:
$dp[i][0]=dp[i-1][0]+dp[i-1][1]$
$dp[i][1]=dp[i-k][0]$
$ans[i]=ans[i-1]+dp[i][0]+dp[i][1]$
初始值设置:dp[0][0]=dp[1][0]=0
由于数据较大,考虑边计算边取模(取模运算分配律)。另外,为了防止取模运算过程中出现负数,在作差时加上mod后再取模。
代码:
#include <bits/stdc++.h> using namespace std; const int N=1e5+5; const int mod=1000000007; int q, k, l, r; int dp[N][3], ans[N];//dp[i][j]表示用j方式到数轴i位置一共的方法数,ans[i]表示从起点0到终点i一共的方法数 void pre() { dp[0][0]=1; for(int i=1;i<=100000;++i){ dp[i][0]=(dp[i-1][0]+dp[i-1][1])%mod; if(i>=k) dp[i][1]=dp[i-k][0]%mod; ans[i]=(ans[i-1]+dp[i][0]+dp[i][1])%mod;//加上ans[i-1] } } int main() { cin>>q>>k; pre(); while(q--){ cin>>l>>r; cout<<(ans[r]-ans[l-1]+mod)%mod<<endl; } return 0; }