[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;
}

浙公网安备 33010602011771号