小 L 的零食

转载:转自洛谷
内存限制:250MB
在这里插入图片描述
在这里插入图片描述
思路: dp+滚动数组优化+前缀和优化
将一个堆的状态分为两种:靠到左边、未靠到左边
具体转移方程见链接。

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);cin.tie(0);
#define _for(i,a,b) for(int i=(a) ;i<=(b) ;i++)
#define _rep(i,a,b) for(int i=(a) ;i>=(b) ;i--)
using namespace std;

typedef long long ll;

const int N = 7e3+10;
const int mod = 998244353;
ll d[N];
ll f[2][N];//f hi-1 >= hi-di
ll g[2][N];//g hi < hi-di
int  main()
{
    
    
    IOS;
    ll n,m;
    cin>>n>>m;
    _for(i,1,n)
    cin>>d[i];
    //第一堆
    _for(i,0,m) f[1][i] = i+1;

    _for(i,2,n)
    {
    
    
        //01滚动数组
        int p = i&1;
        int q = p^1;
        _for(j,0,m)
        {
    
    
            ll l = max(0ll,j-d[i]);
            ll r = min(m,j+d[i-1]);
            //巧妙利用前缀和
            f[p][j] =( ( f[q][m] + g[q][r])  - (l? (f[q][l-1] + g[q][l-1] ) :0) + ( j ? f[p][j-1]:0) +mod)    %mod;
            g[p][j] = ((j ? g[p][j-1] : 0 ) + (l? ( f[q][l-1] +g[q][l-1] ):0 )) %mod;
        }

    }
    cout<< ( f[n&1][m]+g[n&1][m] ) % mod <<endl;
}

猜你喜欢

转载自blog.csdn.net/m0_53688600/article/details/115291459