给定一个整数 k现在,我们可以对 01字符串进行如下操作:
选择其中恰好 k个连续的 1,将它们都变为 0
如果一个 01字符串可以通过若干次上述操作,变为一个全 0字符串,那么就称这个字符串很优秀。
本题共需要回答 T组询问,每组询问给定两个整数 l,r,并请你计算长度在 [l,r] 范围内的所有 01字符串中优秀字符串的数量。
输入格式
第一行包含两个整数 T和 k接下来 T行,每行包含两个整数 l,r
输出格式
共 T行,第 i 行输出第 i 组询问的答案对 10的9次方+7取模后的结果。
数据范围
前三个测试点满足 1≤T,k≤10
所有测试点满足 1≤T,k≤105,1≤l≤r≤105。
输入样例
3 2
1 3
2 3
4 4
输出样例
6
5
5
- 此题是一道动态规划的题,解题思路为:要求l到r之间的优秀串的数量,那就可以先求1 ~ l之间有优秀串的数量,然后减去1 ~ r-1之间的优秀串的数量。求前l个字符串中优秀串的数量,定义为F[l],当第l位为0时就不用管这个零,那么这个时候F[l]=F[l-1],当l位为1时,就要使最后一位和其之前的k-1位都为1最后才能成为一个优秀的串,于是F[l]=F[l-k]。
#include<bits/stdc++.h>
using namespace std;
const int mod=1e9+7;
const int n=100000+5;
int f[n];
int main()
{
///前缀和f[i]表示前i个字符有多少个优秀的串
//那么f[i]=f[i-1]如果最后一位为0时
//如果最后一位为1时则f[i]=f[i-k]
int t,k;
scanf("%d%d",&t,&k);//输入
//定义f,f0=1时满足条件
f[0]=1;
for(int i=1;i<n;i++)
{
if(i-k<0)
{
f[i]=f[i-1];
}
else
f[i]=(f[i-1]+f[i-k])%mod;
}
for(int i=1;i<n;i++) f[i]=(f[i-1]+f[i])%mod;
///求前缀和是因为f[i]仅表示长度为i的优秀串的个数,此时求的是长度小于i的所有优秀串
for(int i=1;i<=t;i++)
{
//输入l和r,结果为fl-fr-1.
int l,r;
scanf("%d%d",&l,&r);
printf("%d\n",(f[r]-f[l-1]+mod)%mod);///注意要+一个mod,否则可能出现负数
}
return 0;
}