「NOI2018」冒泡排序
SOL:
发现求双不降序列的个数。
#include<bits/stdc++.h> #define N 10000007 #define mo 998244353 #define LL long long using namespace std; LL ni[N],fac[N],a[N],T,n,vis[N],mx,res,st; LL qsm(LL x,LL y=mo-2){ static LL anw; for (anw=1;y;y>>=1,x=x*x%mo) if (y&1) anw=anw*x%mo; return anw; } void math_init(){ fac[0]=1; for (int i=1;i<N;i++) fac[i]=fac[i-1]*i%mo; ni[N-1]=qsm(fac[N-1]); for (int i=N-1;i;i--) ni[i-1]=ni[i]*i%mo; } LL g(int i,int j){ LL C1=fac[i+j-2]*ni[i-1]%mo*ni[j-1]%mo; LL C2=j>1?fac[i+j-2]*ni[j-2]%mo*ni[i]%mo:0; return C1-C2<0?C1-C2+mo:C1-C2; } void read(LL &x){ static char c; static int b; for (b=1,c=getchar();!isdigit(c);c=getchar()) if (c=='-') b=-1; for (x=0;isdigit(c);c=getchar()) x=x*10+c-48; x*=b; } signed main () { freopen("inverse.in","r",stdin); freopen("inverse.out","w",stdout); read(T); math_init(); while (T--) { read(n); for (int i=1;i<=n;i++) read(a[i]),vis[i]=0; st=1; mx=0; res=0; for (int i=1;i<=n;i++) { while (vis[st]) ++st; int id=n-i+1,cnt=n-max(mx,a[i]); if (cnt) res=(res+g(id+1,cnt))%mo; vis[a[i]]=1; if (a[i]<mx&&a[i]>st) break; mx=max(a[i],mx); } printf("%lld\n",res); } return 0; }