• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
nannandbk
博客园    首页    新随笔    联系   管理    订阅  订阅
AtCoder Beginner Contest 253 E

AtCoder Beginner Contest 253

E - Distance Sequence

思路:前缀和优化DP

要求$ |a[i]-a[i+1]|>=k\( 定于\)dp[i][j]:\(前\)i\(个数以\)j\(结尾的合法序列数列 \) dp[i][j] += dp[i-1][1~(j-k)]+dp[i-1][(j+k)~m]$

直接写的话复杂度是\(O(nm^2)\)的会TLE,我们发现可以做一个前缀和优化,预处理出上一层的\(dp\)数组的前缀和。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 998244353;

ll n,m,k;
ll dp[1100][5100],s[5500];
int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    cin>>n>>m>>k;
    /*
        |a[i]-a[i+1]|>=k
        dp[i][j]:前i个数以j结尾的合法序列数列
        dp[i][j] += dp[i-1][1~(j-k)]+dp[i-1][(j+k)~m]
    */
    for(int i = 1;i <= m; i++)
        dp[1][i] = 1;
    for(int i = 2;i <= n; i++)
    {
        for(int j = 1;j <= m; j++)
            s[j] = (s[j-1]+dp[i-1][j])%mod;

        for(int j = 1;j <= m; j++)
        {
            //这段代码会T
            // for(int l = 1;l <= j-k; l++)
            // {
            //     dp[i][j] += dp[i-1][l];
            //     dp[i][j] %= mod;
            // }
            // for(int l = j+k;l <= m; l++)
            // {
            //     dp[i][j] += dp[i-1][l];
            //     dp[i][j] %= mod;
            // }

            ll l = j-k,r = j+k;
            if(k==0)
                dp[i][j] += s[m],dp[i][j] %= mod;
            else{
                if(l>=1)
                    dp[i][j] += s[l],dp[i][j] %= mod;
                if(r<=m)
                    dp[i][j] = (dp[i][j]+(s[m]-s[r-1])%mod+mod)%mod;
            }
        }
    }
    ll ans = 0;
    for(int i = 1;i <= m; i++)
        ans += dp[n][i],ans %= mod;
    cout<<ans<<"\n";
    return 0;
}

posted on 2023-09-22 20:01  nannandbk  阅读(17)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3