abc253 E - Distance Sequence

题目链接

abc253 E - Distance Sequence rating : 1073

题目描述

How many integer sequences A = ( A 1 , … , A N ) A=(A_1 ,…,A_N) A=(A1,,AN) of length N N N satisfy all the conditions below?

  • 1 ≤ A i ≤ M ( 1 ≤ i ≤ N ) 1≤A_i ≤M (1≤i≤N) 1AiM(1iN)
  • ∣ A i ​ − A i + 1 ∣ ≥ K ( 1 ≤ i ≤ N − 1 ) ∣A_i​ −A _{i+1} ∣≥K (1≤i≤N−1) AiAi+1∣≥K(1iN1)

Since the count can be enormous, find it modulo 998244353 998244353 998244353.

Constraints
  • 2 ≤ N ≤ 1000 2≤N≤1000 2N1000
  • 1 ≤ M ≤ 5000 1≤M≤5000 1M5000
  • 0 ≤ K ≤ M − 1 0≤K≤M−1 0KM1

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N M K

Output

Print the count modulo 998244353 998244353 998244353.

Sample Input 1

2 3 1

Sample Output 1

6

The following 6 6 6 sequences satisfy the conditions.

  • ( 1 , 2 ) (1,2) (1,2)
  • ( 1 , 3 ) (1,3) (1,3)
  • ( 2 , 1 ) (2,1) (2,1)
  • ( 2 , 3 ) (2,3) (2,3)
  • ( 3 , 1 ) (3,1) (3,1)
  • ( 3 , 2 ) (3,2) (3,2)
Sample Input 2

3 3 2

Sample Output 2

2

The following 2 2 2 sequences satisfy the conditions.

  • ( 1 , 3 , 1 ) (1,3,1) (1,3,1)
  • ( 3 , 1 , 3 ) (3,1,3) (3,1,3)
Sample Input 3

100 1000 500

Sample Output 3

657064711

解法:动态规划

题目的大致意思是:要从 1 ∼ M 1 \sim M 1M 中选出 N N N 个数,这 N N N 个数的数列就为 A A A这个数列 A A A 中每两个相邻的数的差的绝对值必须 大于等于 K K K ∣ A i − A i + 1 ∣ ≥ K |A_i - A_{i+1}| \geq K AiAi+1K

问一共有多少种方案。

我们定义 f ( i , j ) f(i,j) f(i,j)考虑前 i i i 个数,并且最后一个数,也就是第 i i i 个数为 j j j 的方案数量

按照定义最终我们返回的答案就是 ∑ j = 1 M f [ n ] [ j ] \sum_{j = 1}^{M}f[n][j] j=1Mf[n][j]

对于 f [ i ] [ j ] f[i][j] f[i][j], 一共有 { f [ i − 1 ] [ 1 ] , f [ i − 1 ] [ 2 ] , . . . , f [ i − 1 ] [ j − k ] } , { f [ i − 1 ] [ j + k ] , f [ i − 1 ] [ j + k + 1 ] , . . . , f [ i − 1 ] [ m ] } \{ f[i - 1][1],f[i-1][2],...,f[i-1][j-k]\} , \{f[i-1][j+k],f[i-1][j+k+1],...,f[i-1][m] \} {f[i1][1],f[i1][2],...,f[i1][jk]},{f[i1][j+k],f[i1][j+k+1],...,f[i1][m]} 这些状态可以转移到 f [ i ] [ j ] f[i][j] f[i][j]

也就是 f [ i ] [ j ] = ∑ 1 j − k f [ i − 1 ] [ j ] ( j > k ) + ∑ j + k m f [ i − 1 ] [ j ] ( j + k ≤ m ) f[i][j] = \sum_{1}^{j - k}f[i-1][j] (j > k) + \sum_{j + k}^{m}f[i-1][j] (j + k \leq m) f[i][j]=1jkf[i1][j](j>k)+j+kmf[i1][j](j+km)

对于这两段连续的和,我们可以分别使用一个前缀和 p r e pre pre ,一个后缀和 s u f suf suf 数组来进行优化。

初始化: f [ 1 ] [ j ] = 1 ( 1 ≤ j ≤ m ) f[1][j] = 1 \quad (1 \leq j \leq m) f[1][j]=1(1jm),因为只考虑第一个数的时候,无论这个数是 1 ∼ M 1 \sim M 1M 中的哪一个数,都只存在一种方案。

时间复杂度: O ( M × N ) O(M \times N) O(M×N)

C++代码:

#include <iostream>
#include <map>
#include <vector>
#include <algorithm>
#include <numeric>
#include <cstring>

using namespace std;

using LL = long long;

const int N = 1010 , M = 5010, MOD = 998244353;

int n,m,k;

LL f[N][M];
LL pre[M] , suf[M];


void solve(){
    cin>>n>>m>>k;

    //初始化
    for(int j = 1;j <= m;j++) f[1][j] = 1;

    for(int i = 2;i <= n;i++){
        //求前缀和数组 和 后缀和数组
        for(int j = 1;j <= m;j++) pre[j] = (pre[j - 1] + f[i - 1][j]) % MOD;
        for(int j = m;j >= 1;j--) suf[j] = (suf[j + 1] + f[i - 1][j]) % MOD;
        //k > 0 
        if(k){
            for(int j = 1;j <= m;j++){
                if(j > k) f[i][j] = (f[i][j] + pre[j - k]) % MOD;
                if(j + k <= m) f[i][j] = (f[i][j] + suf[j + k]) % MOD;
            }
        }
        else{
            for(int j = 1;j <= m;j++) f[i][j] = pre[m];
        }
    }

    LL ans = 0;
    for(int j = 1;j <= m;j++) ans = (ans + f[n][j]) % MOD;

    cout<<ans<<'\n';
}

int main(){

#ifndef ONLINE_JUDGE

    freopen("in.txt","rt",stdin);
    freopen("out.txt","wt",stdout);

#endif


    int t = 1;

    while(t--){
        solve();
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值