蓝桥OJ3423安全序列

直接去求和,肯定会超时,所以我们利用前缀和来

优化时间复杂度

#include

using namespace std;

using ll=long long;

const ll p=1e9+7;

const int N=1e6+9;

int n,k;

//dp[i]表示以位置i结尾的方案总数

ll dp[N];

ll prefix[N];

int main(){

  ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);

  cin>>n>>k;

  /*这里由于可以从第一个位置放桶或者一个桶都不放,导致这里比较难处理*/

  //以一个空位举例,一共两种方案:一个或不放

  /*这里先考虑当一个桶之前不能放桶时,总方案数prefix[i]为当前的位置加1,这里的1表示不放桶

  当可以放桶时,即i-k-1>0时,相当于在prefix[i-k-1]的后面加了一个桶,对之前没有影响,

  这时prefix[i]是在以第(i-1)个桶为结尾的基础上,加上了以第(i)个桶为结尾的方案数,

  由于prefix[i-k-1]这里面有一种情况是不放桶,所以dp[i]不用加1,相当于只在第i个位置放桶*/

  dp[0]=1;

  prefix[0]=1;

  for(int i=1;i<=n;i++){

    if(i-k-1>0){

      dp[i]=prefix[i-k-1];

      prefix[i]=(prefix[i-1]+dp[i])%p;

    }

    else{

      dp[i]=1;

      prefix[i]=(prefix[i-1]+dp[i])%p;

    }

  }

  cout<<(prefix[n]%p)<

  return 0;

}

你可能感兴趣的:(c++)