run(牛客2018多校二国庆欢乐派对 )
原题:
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.
题意: white cloud喜欢在操场上训练,每一秒他可能走1米或者跑 k k k米,但是他不能连续跑超过1s.现在他要从 L L L跑到 R R R,求总共多少种方法,答案对1000000007取模
Sol:
定义 f [ i ] [ 0 ] f[i][0] f[i][0]表示到 i i i用走的方法数, f [ i ] [ 1 ] f[i][1] f[i][1]表示到 i i i用跑的方法数
则状态转移为 f [ i ] [ 0 ] = f [ i − 1 ] [ 0 ] + f [ i − 1 ] [ 1 ] + 1 , f [ i ] [ 1 ] = f [ i − k ] [ 0 ] + 1 f[i][0]=f[i-1][0]+f[i-1][1]+1,f[i][1]=f[i-k][0]+1 f[i][0]=f[i−1][0]+f[i−1][1]+1,f[i][1]=f[i−k][0]+1
由于不能连续跑,所以 f [ i ] [ 1 ] f[i][1] f[i][1]无法从 f [ i − k ] [ 1 ] f[i-k][1] f[i−k][1]转移过来,因为如果从 f [ i − k ] [ 1 ] f[i-k][1] f[i−k][1]转移过来,说明 i − k i-k i−k是从前面某一点 p p p跑过来的,再从 i − k i-k i−k跑到 i i i,连续跑了,不符合题意。
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const ll mod=1000000007;
const int N=1e5+10;
ll f[N][2];
int main()
{
int q,k;
while(scanf("%d%d",&q,&k)!=EOF)
{
f[0][0]=0;
for(int i=1;i<=1e5;i++)
{
if(i<k) f[i][0]=(f[i-1][0]+1)%mod;
else
{
f[i][0]=(f[i-1][0]+f[i-1][1]+1)%mod;
f[i][1]=(f[i-k][0]+1)%mod;
}
}
for(int i=1;i<=q;i++)
{
int l,r;
cin>>l>>r;
ll res=((f[r][1]+f[r][0])-(f[l-1][0]+f[l-1][1]))%mod;
cout<<res<<endl;
}
}
}