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

函數順序是爲了方便看。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章