P17693 砕月 题解
由于直接从填数的角度出发很复杂,而且题目问的是最终排列的数量,那就先考虑什么样的最终排列是合法的。
结论是,\(\forall i\in [1,n],v=a_i,x_v \le i \lor y_v \le \max_{j<i}a_j\) 是最终排列合法的充要条件。
证明:
1.充分性:直接按顺序填就是了。
2.必要性:当最终排列合法时,前面尚有空位的前缀 \(\max\) 亦小于,则必然也小于最终无空位的前缀最大值了。
所以我们把问题转化成了对满足要求的排列计数的问题。
考虑 DP,设 \(f_{i,j}\) 表示填了前 \(i\) 个位置,前缀最大值为 \(j\) 的方案数。转移显然分为更新最大值和不更新两种。
1.考虑不更新最大值,令 \(cnt_{i,j}\) 表示 \(x_k\le i\) 或者 \(v_k \le j\) 且 \(k<j\) 的数量,则 \(f_{i+1,j} \leftarrow f_{i,j}\times (cnt_{i+1,j}-i)\),因为前面选的 \(i\) 个数条件更加严格,所以一定在这 \(cnt_{i,j}\) 个数中。
2.更新了最大值,则 \(f_{i+1,k} \leftarrow f_{i,j}\),这个转移是 \(O(n^3)\) 的,无法通过。
考虑优化,更新最大值的 \(k\) 有两种情况,一是 \(x_k \le i+1\),则 \(f_{i+1,k} \leftarrow \sum_{j<k} f_{i,j}\)。二是 \(x_k >i+1 \land y_k \le k\),则 \(f_{i+1,k} \leftarrow \sum_{v_k \le j<k}f_{i,j}\),两个式子都可以前缀和优化。时间复杂度 \(O(n^2)\)。
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define _int __int128
#define ull unsigned long long
#define pii pair<int,int>
#define fst first
#define scd second
#define pq priority_queue
#define mkp make_pair
#define popcount(x) __builtin_popcount(x)
int T,n;
const int N = 5e3+10,mod=998244353;
int x[N],y[N],f[N][N],cnt[N][N],s[N],pre[N];
inline void add(int &x,int y){
x=(x+y>=mod)?x+y-mod:x+y;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0),cout.tie(0);
cin>>T;
while(T--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>x[i];
}
for(int i=1;i<=n;i++){
cin>>y[i];
}
for(int j=1;j<=n;j++){
int cj=0;
for(int i=0;i<=n;i++)s[i]=0;
for(int v=1;v<=j;v++){
if(y[v]<=j){
cj++;
}else{
s[x[v]]++;
}
}
for(int i=1;i<=n;i++){
(s[i]+=s[i-1])%=mod;
cnt[i][j]=(s[i]+cj)%mod;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++)f[i][j]=0;
}
for(int i=1;i<=n;i++){
if(1>=x[i])f[1][i]=1;
pre[i]=(pre[i-1]+f[1][i])%mod;
}
for(int i=1;i<n;i++){
for(int j=i;j<=n;j++){
add(f[i+1][j],(f[i][j]*(cnt[i+1][j]-i+mod)%mod)%mod);
}
for(int k=i+1;k<=n;k++){
if(x[k]<=i+1){
add(f[i+1][k],pre[k-1]);
}else{
add(f[i+1][k],(pre[k-1]-pre[y[k]-1]+mod)%mod);
}
}
pre[0]=0;
for(int j=1;j<=n;j++){
pre[j]=(pre[j-1]+f[i+1][j])%mod;
}
}
cout<<f[n][n]<<endl;
}
return 0;
}

浙公网安备 33010602011771号