[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: 复制
3
2 2 2
输出样例#1: 复制
6

说明

满足条件的序列有 [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
",ans);           
29     return 0;
30 }
原文地址:https://www.cnblogs.com/HocRiser/p/8806973.html