There is a straight highway with N storages alongside it labeled by 1,2,3,...,N. Bob asks you to paint all storages with two colors: red and blue. Each storage will be painted with exactly one color.
Bob has a requirement: there are at least M continuous storages (e.g. "2,3,4" are 3 continuous storages) to be painted with red. How many ways can you paint all storages under Bob's requirement?
Input
There are multiple test cases.
Each test case consists a single line with two integers: N and M (0<N, M<=100,000).
Process to the end of input.
Output
One line for each case. Output the number of ways module 1000000007.
Sample Input
4 3
Sample Output
3
首先不能使用二维dp,因为n,m为100000,空间大小会超.
dp[i]表示n==i时满足条件的涂色方案数.
故for(int i=1;i<m;++i) dp[i]=0;
dp[m]=1;
当i>m时,考虑前i-1个物体的染色情况:
1.前i-1个物体满足条件时,最后一个涂色随意,故共 2*dp[i-1] 种;
2.前i-1个物体不满足条件时,则最后一个一定要为red,且前i-1个物体中最后连续m-1个物体也是red,且前i-1个物体中倒数第m个物体一定是blue,且前i-m-1个物体不满足条件;故方案数为: pow(2,i-m-1)-dp[i-m-1] 种;
综上,dp[i]=2*dp[i-1]+pow(2,i-m-1)-dp[i-m-1]
附上代码:
# include <stdio.h>
# include <math.h>
# define p 1000000007
long long dp[100100];
long long _pow (long long a,int n)
{
long long r=1;
while (n)
{
if(n%2==1)
{
r=((r%p)*a)%p;
n=n-1;
}
a=((a%p)*(a%p))%p;
n=n/2;
}
return r%p;
}
int main ()
{
int n,m,i,j;
long long ans;
while(scanf("%d",&n)!=EOF)
{
scanf("%d",&m);
for(i=0;i<m;i++)
{
dp[i]=0;
}
dp[m]=1;
for(i=m+1;i<=n;i++)
{
dp[i]=((dp[i-1]*2)%p+_pow(2,i-m-1)-dp[i-m-1])%p;//注意取模可能得到负数
}
printf("%lld\n",(dp[n]+p)%p);//防止取模得到负数
}
return 0;
}