CF960G Bandit Blues(第一類斯特林數)
阿新 • • 發佈:2019-01-02
可以去看看litble巨巨關於第一類斯特林數的總結
設\(f(i,j)\)為\(i\)個數的排列中有\(j\)個數是字首最大數的方案數,列舉最小的數的位置,則有遞推式\(f(i,j)=f(i-1,j-1)+(i-1)\times f(i-1,j)\)
這個就是第一類斯特林數
第一類斯特林數中\(S_1(n,m)\)是\(\prod_{i=0}^{n-1}(x+i)\)中\(x^m\)的係數,可以用分治\(FFT\)做到\(O(n\log^2n)\)的複雜度
首先\(n\)肯定是字首最大值,所以題目要求的\(a-1\)個數一定都在\(n\)前面,\(b-1\)個數一定都在\(n\)
//minamoto #include<bits/stdc++.h> #define R register #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i) #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i) #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v) using namespace std; char buf[1<<21],*p1=buf,*p2=buf; inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;} int read(){ R int res,f=1;R char ch; while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1); for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0'); return res*f; } const int N=5e5+5,P=998244353,Gi=332748118; inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;} inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;} inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;} int ksm(R int x,R int y){ R int res=1; for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x); return res; } int A[19][N],O[N],r[N]; int n,m,a,b; void NTT(int *A,int ty,int lim){ fp(i,0,lim-1)if(i<r[i])swap(A[i],A[r[i]]); for(R int mid=1;mid<lim;mid<<=1){ R int I=(mid<<1),Wn=ksm(ty==1?3:Gi,(P-1)/I);O[0]=1; fp(i,1,mid-1)O[i]=mul(O[i-1],Wn); for(R int j=0;j<lim;j+=I)for(R int k=0;k<mid;++k){ int x=A[j+k],y=mul(O[k],A[j+k+mid]); A[j+k]=add(x,y),A[j+k+mid]=dec(x,y); } }if(ty==-1)for(R int i=0,inv=ksm(lim,P-2);i<lim;++i)A[i]=mul(A[i],inv); } void solve(int ql,int qr,int d){ if(ql==qr)return (void)(A[d][0]=ql,A[d][1]=1); int mid=(ql+qr)>>1,lim=1,l=0; while(lim<=qr-ql+1)lim<<=1,++l; solve(ql,mid,d),solve(mid+1,qr,d+1); fp(i,0,lim-1)r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)); fp(i,mid-ql+2,lim-1)A[d][i]=0; fp(i,qr-mid+1,lim-1)A[d+1][i]=0; NTT(A[d],1,lim),NTT(A[d+1],1,lim); fp(i,0,lim-1)A[d][i]=mul(A[d][i],A[d+1][i]); NTT(A[d],-1,lim); } int C(int n,int m){ int k1=1,k2=1; fp(i,n-m+1,n)k1=mul(k1,i); fp(i,1,m)k2=mul(k2,i); return mul(k1,ksm(k2,P-2)); } int main(){ // freopen("testdata.in","r",stdin); n=read(),a=read(),b=read(); if(!a||!b||a+b-2>n-1)return puts("0"),0; if(n==1)return puts("1"),0; solve(0,n-2,0); printf("%d\n",mul(A[0][a+b-2],C(a+b-2,b-1))); return 0; }