【BNU Summer Training 2014.07.25】 Painting Storages (dp)

本文探讨了一种特定的涂色问题:在一条直线上有N个存储单元,需要使用红色和蓝色进行涂色,其中至少有M个连续的存储单元必须被涂成红色。文章提供了解决该问题的一种动态规划算法,并附带了实现这一算法的C++代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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;
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值