不难发现一个性质,若对于 Ai−1 A i − 1 的限制是 Li−1≤Ai−1≤Ri−1 L i − 1 ≤ A i − 1 ≤ R i − 1 ,对于 Ai A i 的限制是 Li≤Ai≤Ri L i ≤ A i ≤ R i ,那么有 Li−1≤Li L i − 1 ≤ L i , Ri−1≥Ri R i − 1 ≥ R i ,于是我们考虑DP。
设 fi,x,l,r f i , x , l , r 表示填了 i i 个数, Ai A i 为 x x , A1..i−1 A 1.. i − 1 中 ≤x ≤ x 的最大值是 l l , ≥x ≥ x 的最小值是 r r (注意 l,r l , r 不是限制 Ai A i 的范围)的方案数。
对于 x,l,r x , l , r 互不相等的状态, Ai−1 A i − 1 必然充当了 l l 或者 r r ,转移就是 fi,x,l,r←∑k≤lfi−1,l,k,r+∑k≥rfi−1,r,l,k f i , x , l , r ← ∑ k ≤ l f i − 1 , l , k , r + ∑ k ≥ r f i − 1 , r , l , k 。
对于 x,l,r x , l , r 只有两者相等的状态显然是不存在的。
对于 x,l,r x , l , r 全相等的状态需要特殊处理,因为 Ai−1 A i − 1 不一定充当了 l l 或 r r ,可能是之前一个 =x = x 的数充当了两者,所以讨论两种情况:
1. Ai−1=x A i − 1 = x ,这时 fx,x,x←∑j≤x∑k≥xfi−1,x,j,k f x , x , x ← ∑ j ≤ x ∑ k ≥ x f i − 1 , x , j , k 。
2. Ai−1≠x A i − 1 ≠ x ,这时 fx,x,x←∑y≠x(∑k≤yfi−1,y,k,x+∑k≥yfi−1,y,x,k) f x , x , x ← ∑ y ≠ x ( ∑ k ≤ y f i − 1 , y , k , x + ∑ k ≥ y f i − 1 , y , x , k ) 。
然后用前缀和维护一些 ∑k≤x,∑k≥x ∑ k ≤ x , ∑ k ≥ x 什么的就可以把复杂度降到 O(nmax3{ai}) O ( n max 3 { a i } ) 了。
代码:
#include
#include
#include
#define ui unsigned int
using namespace std;
const int mod=998244353;
ui n,r[55],mxr,f[155][155][155],sl[155][155][155],sr[155][155][155];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&r[i]);
mxr=max(mxr,r[i]+1);
}
for(int i=0;i<=mxr;i++)
sl[0][i][mxr]=sr[0][0][i]=1;
for(int i=1;i<=n;i++)
{
memset(f,0,sizeof(f));
for(int ai=1;ai<=r[i];ai++)
{
for(int L=0;Lfor(int R=ai+1;R<=mxr;R++)
f[ai][L][R]=(sl[L][L][R]+sr[R][L][R])%mod;
for(int R=ai;R<=mxr;R++)
f[ai][ai][ai]=(f[ai][ai][ai]+sl[ai][mxr][R])%mod;
for(int ai_1=0;ai_1<=mxr;ai_1++)
if(ai_1!=ai)
f[ai][ai][ai]=(f[ai][ai][ai]+sl[ai_1][ai_1][ai]+sr[ai_1][ai][ai_1])%mod;
}
memset(sl,0,sizeof(sl));
for(int ai=1;ai<=r[i];ai++)
for(int L=0;L<=mxr;L++)
for(int R=ai;R<=mxr;R++)
sl[ai][L][R]=(f[ai][L][R]+(L==0?0:sl[ai][L-1][R]))%mod;
memset(sr,0,sizeof(sr));
for(int ai=1;ai<=r[i];ai++)
for(int L=0;L<=ai;L++)
for(int R=mxr;R>=0;R--)
sr[ai][L][R]=(f[ai][L][R]+sr[ai][L][R+1])%mod;
}
ui ans=0;
for(int ai=1;ai<=r[n];ai++)
for(int L=0;L<=ai;L++)
for(int R=ai;R<=mxr;R++)
ans=(ans+f[ai][L][R])%mod;
printf("%d",ans);
return 0;
}