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

 

posted @ 2018-08-16 20:09  泪寒之雪  阅读(415)  评论(0编辑  收藏  举报