[ARC104] F - Visibility Sequence

题面

题目描述

给定一个长度为 \(n\) 的限制数组 \(lim\),令 \(X\) 为任意满足 \(\forall 1\leq i\leq n,X_i\in [1,lim_i]\) 的数组。令 \(P_i\)\([1,i)\) 中最后一个大于 \(X_i\) 的位置,没有则为 \(-1\)。求不同的 \(P\) 的个数。

数据范围

  • \(1\leq n \leq 100\)

  • \(1\leq X_i\leq 10^5\)

题解

简单 DP 都不会,倒闭了 /ll。

\(f_{i,j,k}\) 表示区间 \([i,j]\) 中的数不大于 \(k\) 所构成的 \(P[i:j]\) 的方案数。

有转移:\(\displaystyle f_{i,j,k}=\sum_{p=i}^j f_{i,p-1,k}f_{p+1,j,k-1}\)

这相当于钦定 \(P[p+1:k]\) 中的 \(-1\) 全替换为 \(p\)

注意到大于 \(n\) 的取值并不会生成新的 \(P\),于是 \(O(n^4)\) 暴力转移即可。

#include<bits/stdc++.h>

using namespace std;

#define endl '\n'
const int N=1e2+9;
const int mod=1e9+7;

int f[N][N][N],a[N],n;

signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);

    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i],a[i]=min(a[i],n);

    for(int i=0;i<=n;i++) for(int j=0;j<=n;j++) f[i+1][i][j]=1;
    for(int len=1;len<=n;len++){
        for(int i=1;i<=n-len+1;i++){
            int j=i+len-1;
            for(int p=i;p<=j;p++){
                for(int k=1;k<=n;k++){
                    f[i][j][k]+=1ll*f[i][p-1][min(k,a[p])]*f[p+1][j][min(k,a[p])-1]%mod;
                    if(f[i][j][k]>=mod) f[i][j][k]-=mod;
                }
            }
        }
    }

    cout<<f[1][n][n]<<endl;

    return 0;
}
posted @ 2025-04-09 13:59  JoeyJiang  阅读(12)  评论(0)    收藏  举报