Codeforces 474D 蛋糕(dp-递推)

这里写图片描述

无敌水题,实际上样例解释就暴露了它递推的本质。

f[ i ]表示吃 i 个蛋糕的方案数。
那么,f[ i ]=f[ i-1 ]+f[ i-k ]; ( i >k )
这个递推和走楼梯很像。即当前i个蛋糕,可以分为两种情况:吃掉一个蛋糕,剩下蛋糕的方案数即为f[ i-1 ];或者选择吃掉k个蛋糕,剩下蛋糕的方案数为f[ i-k ]。

初始化:i < k: f[ i ]=1;
i==k:f[ i ]=2;
显然。

处理完之后再对数组求个前缀和,查询时输出即可。

值得(我)注意的是,减法取模x:A=ax+y( 全是整数 ) ,B=a’x+y’ ( a > a’,y < y’ ),A-B=( a-a’ )x+y-y’,因为 y-y’<0 ,所以自动地,A-B=(a-a’-1)x+x+y-y’ ,再取模:(A-B)%x=x+y-y’; 而我以前没接触过这个套路,对于已取模的A=y,B=y’,A-B=y-y’,然后就,GG啦!
正确操作:( A-B+x)%x。这种失误错过一次应该就会了解。

int main()
{
    x=10000000;y=0;
    read(t);read(k);
    for(int i=1;i<=t;++i) 
    {
        read(a[i].x);read(a[i].y);
        x=min(x,a[i].x);y=max(y,a[i].y);
    }//先存是因为想先确定查询上下界求前缀,其实不太有必要,耗时空可能更多。
    work_();
    out_();
    return 0;
}

void work_()
{
    memset(f,0,sizeof(f));
    for(int i=1;i<k;++i) f[i]=1LL;
    f[0]=0LL;f[k]=2LL;//初始化。
    for(int i=k+1;i<=y;++i) f[i]=1LL*(f[i-1]+f[i-k])%1000000007;
    for(int i=x;i<=y;++i)
        f[i]=(f[i]+f[i-1])%1000000007;
}



void out_()
{
    for(int i=1;i<=t;++i)
    {
        printf("%lld\n",(f[a[i].y]+1000000007-f[a[i].x-1])%1000000007);
    }
}

函数顺序是为了方便看。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值