原题链接:https://atcoder.jp/contests/abc159/tasks/abc159_f
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const long long mod=998244353;
const int N=3010;
int n,s;
int a[N];
long long dp[N][N][3];//dp[i][s][t],从前i个里选,总和为s,状态为t的方案数
/*
假设某个方案可以满足加起来等于s
它包含在区间[left,right)上,那么每个包含该区间的区间,都含有该方案
状态0:左右端点不作规定
状态1:左端点已确定(的小区间方案数)
状态2:左右端点都已确定(的小区间的方案数)
*/
int main(){
cin>>n>>s;
for(int i=0;i<n;i++) cin>>a[i];
dp[0][0][0] = 1;
for(int i=0;i<n;i++){
for(int j=0;j<=s;j++){
//以下三种状态不选取第i+1个数
(dp[i+1][j][0] += dp[i][j][0]) %= mod;
//在前i个里面选,总和为j的方案,必然包含于在前i+1个里选,总和为j的方案
(dp[i+1][j][1] += dp[i][j][0] + dp[i][j][1]) %= mod;
//不论左端点是否确定,它们都包含在“前i+1个里选,总和为j,左端点确定”的方案内
(dp[i+1][j][2] += dp[i][j][0] + dp[i][j][1] + dp[i][j][2]) %= mod;
//前i个里所确定的右端点也不会超出前i+1个里确定的右端点
if(j + a[i] <= s){
//以下两种状态选取第i+1个数
(dp[i+1][j+a[i]][1] += dp[i][j][0] + dp[i][j][1]) %= mod;
(dp[i+1][j+a[i]][2] += dp[i][j][0] + dp[i][j][1]) %= mod;
//这里若dp[i][j][2]确定了右端点,则不能选取第i+1个数
}
}
}
cout<<dp[n][s][2]<<endl;
return 0;
}
//昏过去