cf-474D题解
CF-474D
-
很多人说是个dp,但其实更多的应该和数学递推关系更大,其实和紫书上的fibonacci数列的递推方法一样
-
我们先假设k=2,len=5时:
5=1+1+1+1+1(RRRRR)
5=2+1+1+1(WWRRR)
5=1+2+1+1(RWWRRR)
5=1+1+2+1(RRWWR)
5=1+1+1+2(RRRWWW)
5=2+2+1(WWWWR)
5=2+1+2(WWRWW)
5=1+2+2(RWWWW)
- 其中有5种方法第一次先选了R,有3种方法第一次先选了W。
- 假设f(n)为长度为n的排列的排列总数,把n长度的排列方法分为两类。
- 第一类:第一步选R,还剩下n-1长度要选,有f(n-1)
- 第二类:第一步选W,还剩下n-2长度要选,有f(n-2) (类比,当其他情况时把2换成k就行)
- 所以得到的递推式 f(n)=f(n-1)+f(n-k)
#include<bits/stdc++.h>
using namespace std;
#pragma GCC optimize(2)
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const int NUM=1e5+10;
const ll MOD=1e9+7;
ll n,k;
ll d[NUM],sum[NUM];
void slove()
{
d[0]=1;
for(int i=1;i<=NUM;++i){
d[i]=(d[i-1]);
d[i]%=MOD;
if(i>=k){
d[i]+=(d[i-k]%MOD);
d[i]%=MOD;
}
}
sum[0]=0;
for(int i=1;i<=NUM;++i){
sum[i] = (sum[i-1]%MOD + d[i]%MOD+MOD)%MOD;
}
//for(int i=0;i<=100;++i) cout<<sum[i]<<"\n";
}
int main()
{
ios::sync_with_stdio(false);
cin>>n>>k;
slove();
for(int i=1;i<=n;++i){
//cin>>a[i]>>b[i];
int a,b;
cin>>a>>b;
cout<<(sum[b]-sum[a-1]+MOD)%MOD<<"\n";
}
return 0;
}