1. 程式人生 > >「NOI2018」冒泡排序

「NOI2018」冒泡排序

() 冒泡 col mes void init static max nbsp

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

「NOI2018」冒泡排序