验证一下·,带入$a=b-1=n$ (注意我们是从(0,1)出发),我们就得到了常规的卡塔兰数的公式$C_n=C(n,2n)-C(n-1,2n)$。
在推出上述公式以后,代码方面难度极低,只需要处理好一些必备的前缀数组,会算组合数模$P$就行,这都在提高组的要求以内,想必对NOI选手是小菜一碟。
```cpp
#include <iostream>
#include <cstring>
using namespace std;
long long const N=1e6+3e5,P=998244353;
int n,t,p[N],r[N],sr[N],pr[N];
long long ans,fac[N],inv[N];
long long power(long long x, long long k){
k=(k+P-1) % (P-1);
long long ans=1;
for (long long i=1;i<=k;i*=2,x=(x*x) % P)
if (k & i) ans=(ans*x) % P;
return ans;
}
long long c(long long a, long long b){
if (a<0) return 0;
return fac[b]*inv[a] % P * inv[b-a] % P;
}
long long g(long long a, long long b){
return (c(a,a+b-1)-c(a-1,a+b-1)+P) % P;
}
int main(){
ios::sync_with_stdio(false);
fac[0]=inv[0]=1;
for (int i=1;i<N;i++){
fac[i]=fac[i-1]*i % P;
inv[i]=power(fac[i],P-2);
}
cin>>t;
while (t--){
cin>>n;
ans=0;
for (int i=1;i<=n;i++){
cin>>p[i];
r[i]=max(r[i-1],p[i]);
if (r[i-1]>p[i]) pr[i]=max(pr[i-1],p[i]); else pr[i]=pr[i-1];
}
sr[n]=p[n];
for (int i=n-1;i>=1;i--)
sr[i]=min(sr[i+1],p[i]);
for (int i=1;i<=n;i++){
if (r[i]<n) ans=(ans+g(n-r[i]-1,n-i+2)) % P;
if (pr[i-1]>p[i]) break;
if (i<n && p[i]<r[i-1] && (p[i]>sr[i+1])) break;
}
cout<<ans<<endl;
}
return 0;
}
```