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;
}
posted @ 2020-07-11 20:57  0xDkXy_DWM  阅读(134)  评论(0编辑  收藏  举报