CF960Ghtml
設\(f(i,j)\)爲\(i\)個數的序列,有\(j\)個前綴最大值的方案數c++
咱們考慮每次添一個最小數,則有:\(f(i,j)=f(i-1,j)+(i-1)*f(i-1,j-1)\),顯然這是第一類斯特林數spa
從而咱們獲得一個樸素的答案:\[Ans=\sum\limits_{i=1}^{n}f_{i,a-1}×f_{n-1-i,b-1}×C_{n-1}^i\]code
理解:枚舉\(i+1\)爲最大值添的位置,則已限制了前綴最值個數及後綴最值個數,而後再乘上前半部分所填的數htm
觀察\(f_{i,a-1}×f_{n-1-i,b-1}\),發現第一維和惟一:\[Ans=\begin{bmatrix}n-1\\a+b-2\end{bmatrix}C_{a+b-2}^{a-1}\]blog
可能會有點難理解:等同於分類成\(a+b-2\)個環,而環是不考慮順序的,因此咱們選擇不考慮打亂順序地選擇環get
至此,咱們惟一須要的就是快速求出第一類斯特林數\(\begin{bmatrix}n-1\\a+b-2\end{bmatrix}\)it
即便是單個數也沒法有特殊的公式快速得出,因此咱們用與求整行第一類斯特林數的方法求出class
\(O(nlog^2n)\)的方法已經爛大街了,分治一下就行方法
\(O(nlogn)\):因爲涉及到公式推倒,不是本題解的重點
移步淺談斯特林數與斯特林反演,內有詳細證實推倒及代碼
#include<bits/stdc++.h> typedef int LL; const LL mod=998244353,g=3,_g=332748118,maxn=2e5+9; inline LL Pow(LL base,LL b){ LL ret(1); while(b){ if(b&1) ret=1ll*ret*base%mod; base=1ll*base*base%mod; b>>=1; }return ret; } LL r[maxn],W[maxn]; inline LL Fir(LL n){ LL limit(1),len(0),up(n<<1); while(limit<up){ limit<<=1; ++len; } for(LL i=0;i<limit;++i) r[i]=(r[i>>1]>>1)|((i&1)<<len-1); return limit; } inline void NTT(LL *a,LL n,LL type){ for(LL i=0;i<n;++i) if(i<r[i]) std::swap(a[i],a[r[i]]); for(LL mid=1;mid<n;mid<<=1){ LL wn(Pow(type?g:_g,(mod-1)/(mid<<1))); W[0]=1; for(LL i=1;i<mid;++i) W[i]=1ll*W[i-1]*wn%mod; for(LL R=mid<<1,j=0;j<n;j+=R) for(LL k=0;k<mid;++k){ LL x(a[j+k]),y(1ll*W[k]*a[j+mid+k]%mod); a[j+k]=1ll*(x+y)%mod; a[j+mid+k]=1ll*(x-y+mod)%mod; } } } LL T[maxn],F[maxn],H[maxn],fac[maxn],fav[maxn],tmp[maxn],sum[maxn],B[maxn]; inline LL Mul(LL n,LL *a,LL *b,LL *ans){ LL limit(Fir(n)); NTT(a,limit,1); NTT(b,limit,1); for(LL i=0;i<limit;++i) ans[i]=1ll*a[i]*b[i]%mod; NTT(ans,limit,0); for(LL i=((n-1)<<1)+1;i<limit;++i) a[i]=b[i]=0; return Pow(limit,mod-2); } inline void Solve(LL n,LL *a){ if(!n){ a[0]=1; return; } if(n==1){ a[1]=1; return; } LL len(n/2); Solve(len,a); for(LL i=0;i<=len;++i){ F[i]=1ll*Pow(len,i)*fav[i]%mod; H[i]=1ll*fac[i]*a[i]%mod; } std::reverse(H,H+len+1); LL limit(Fir(len+1)); NTT(F,limit,1); NTT(H,limit,1); for(LL i=0;i<limit;++i) F[i]=1ll*F[i]*H[i]%mod; NTT(F,limit,0); LL ty(Pow(limit,mod-2)); for(LL i=0;i<=len;++i) tmp[i]=1ll*F[len-i]*ty%mod*Pow(fac[i],mod-2)%mod; for(LL i=(len<<1);i<=limit;++i) F[i]=H[i]=0; LL val(Mul(len+1,a,tmp,B)); for(LL i=0;i<=(len<<1);++i) a[i]=1ll*B[i]*val%mod; if(n&1) for(LL i=n;i>=1;--i) a[i]=1ll*(a[i-1]+1ll*(n-1)*a[i]%mod)%mod; } LL n,a,b,m; LL ans[maxn]; int main(){ scanf("%d%d%d",&n,&a,&b); LL val; val=fac[0]=fac[1]=1; for(LL i=2;i<=n;++i) val=fac[i]=1ll*val*i%mod; val=fav[n]=Pow(fac[n],mod-2); for(LL i=n;i>=1;--i) val=fav[i-1]=1ll*val*i%mod; Solve(n-1,ans); n=a+b-2; m=a-1; printf("%d\n",1ll*ans[n]*fac[n]%mod*fav[m]%mod*fav[n-m]%mod%mod); }