[P4063][JXOI2017]数列(DP)
题目描述
九条可怜手上有一个长度为 n 的整数数列 ri,她现在想要构造一个长度为 n 的,满足如下条件的整数数列 A:
• 1 ≤ Ai ≤ ri。
• 对于任意 3 ≤ i ≤ n,令 R 为 A1 至 Ai−2 中大于等于 Ai−1 的最小值,L 为 A1 至 Ai−2中小于等于 Ai−1 的最大值。Ai 必须满足 L ≤ Ai ≤ R。如果不存在大于等于 Ai−1 的,那么 R = +∞;如果不存在小于等于 Ai−1 的,那么 L = −∞。
现在可怜想要知道共有多少不同的数列满足这个条件。两个数列 A 和 B 是不同的当且仅当至少存在一个位置 i 满足 Ai ≠ Bi。
输入输出格式
输入格式:
第一行输入一个整数 n,第二行输入 n 个整数 ri。
输出格式:
输出一个整数表示方案数,答案可能很大,对 998244353 取模后输出。
输入输出样例
说明
满足条件的序列有 [1, 1, 1], [1, 2, 1], [1, 2, 2], [2, 1, 1], [2, 1, 2], [2, 2, 2]。
测试点编号
1.2 n<=7 ri<=7 3.4 n<=50 ri<=10 5.6 n<=50 ri<=16 7.8 n<=50 ri<=50 9.10 n<=50 ri<=150
https://blog.csdn.net/dofypxy/article/details/79145068
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define rep(i,l,r) for (int i=l; i<=r; i++) 5 using namespace std; 6 7 const int N=155,mod=998244353; 8 int n,ans,r[N],mx,f[N][N][N],sl[N][N][N],sr[N][N][N]; 9 10 int main(){ 11 freopen("P4063.in","r",stdin); 12 freopen("P4063.out","w",stdout); 13 scanf("%d",&n); 14 rep(i,1,n) scanf("%d",&r[i]),mx=max(mx,r[i]+1); 15 rep(i,0,mx) sl[0][i][mx]=sr[0][0][i]=1; 16 rep(i,1,n){ 17 memset(f,0,sizeof(f)); 18 rep(a,1,r[i]){ 19 rep(L,0,a-1) rep(R,a+1,mx) f[a][L][R]=(sl[L][L][R]+sr[R][L][R])%mod; 20 rep(R,a,mx) f[a][a][a]=(f[a][a][a]+sl[a][mx][R])%mod; 21 rep(a1,0,mx) if (a1!=a) f[a][a][a]=(f[a][a][a]+sl[a1][a1][a]+sr[a1][a][a1])%mod; 22 } 23 memset(sl,0,sizeof(sl)); memset(sr,0,sizeof(sr)); 24 rep(a,1,r[i]) rep(L,0,mx) rep(R,a,mx) sl[a][L][R]=(f[a][L][R]+(L ? sl[a][L-1][R] : 0))%mod; 25 rep(a,1,r[i]) rep(L,0,a) for (int R=mx; ~R; R--) sr[a][L][R]=(f[a][L][R]+sr[a][L][R+1])%mod; 26 } 27 rep(a,1,r[n]) rep(L,0,a) rep(R,a,mx) ans=(ans+f[a][L][R])%mod; 28 printf("%d\n",ans); 29 return 0; 30 }