Codeforces 474D. Flowers
传送门:https://codeforces.com/problemset/problem/474/D
提醒自己:
有时把一些会在多个步骤中重复使用到的东西要先分离出来算好(本题具体见///中部分),这样可以节省时间,在这道题中使用了这个方法,其实在上之前做474B也用到了这个思想。
题目大意:
现在有红色和白色的花瓣两种,对它们进行一个排序,使得要么没有白色的,要么白色的都是k个一组连在一起。你的任务是算从ai到bi个花瓣排列种数一共有多少种不同的排列方法。
主要想法:
我们可以发现在前k-1个都只有全红一种方法,而k有2个,此后,每一个i都是i-1的情况加上一个红色或者i-k的情况加上k个折色,所以这个函数就推出来了。
dp[i]=dp[i-1]+dp[i-k]
但我们也要关注到的是如何求ai到bi,直接分次暴力累加应该会超时吧,所以我们不妨这样
///把每个dp定义为它原来前面每个dp的和,这样,ai到bi就变成了两个dp之间的差,这样,dp的运算就可以循环利用,节省了时间///
代码实现:
#include <bits/stdc++.h>
using namespace std;
#define P 1000000007
int main()
{
int t,k,m=0;
cin>>t>>k;
vector<int>a(t),b(t);
for(int i=0;i<t;i++)
{
scanf("%d%d",&a[i],&b[i]);
if(m<b[i])m=b[i];
}
if(k>m)
{
for(int i=0;i<t;++i)
{
cout<<b[i]-a[i]+1<<endl;
}
}
else
{
vector<int>c(m+1,0);
for(int i=1;i<k;++i)
{
c[i]=1;
}
c[k]=2;
for(int i=k+1;i<=m;++i)
{
c[i]=(c[i-1]+c[i-k])%P;
}
for(int i=2;i<=m;i++)
{
c[i]=(c[i]+c[i-1])%P;
}
for(int i=0;i<t;i++)
{
int x=c[b[i]]-c[a[i]-1];
x=x>=0?x:x+P;
cout<<x<<endl;
}
}
return 0;
}