codeforces 960G Bandit Blues
正解:第一类斯特林数,分治$FFT$。
这道题是$FJOI2016$建筑师的加强版。
首先答案是$S_{u}(n-1,a+b-2)*\binom{a+b-2}{a-1}$,比较简单就不推了。。
知道这个以后再知道第一类斯特林数的递推式,$FJOI$那题就能做了。
但是递推式的复杂度是$O(nm)$的,我们考虑怎么直接求一行的斯特林数。
我们把$x$的$n$次上升幂展开,即可得到一个多项式,而这个多项式的$m$次项系数即为$S_{u}(n,m)$。
有符号的斯特林数类似,换成下降幂即可。
这两个结论的证明也很显然,直接对照递推式就会发现是对的。
然后就可以用分治$FFT$做了,似乎有$nlogn$的做法,偷懒就不学了。。
1 #include <bits/stdc++.h> 2 #define il inline 3 #define RG register 4 #define ll long long 5 #define pb push_back 6 #define ysf (998244353) 7 #define N (500005) 8 9 using namespace std; 10 11 vector<int> vec[N]; 12 13 int rev[N],A[N],B[N],n,a,b,lg,len; 14 15 il int qpow(RG int a,RG int b){ 16 RG int ans=1; 17 while (b){ 18 if (b&1) ans=1LL*ans*a%ysf; 19 if (b>>=1) a=1LL*a*a%ysf; 20 } 21 return ans; 22 } 23 24 il void NTT(int *a,RG int n,RG int f){ 25 for (RG int i=0;i<len;++i) if (i<rev[i]) swap(a[i],a[rev[i]]); 26 for (RG int i=1,wn;i<n;i<<=1){ 27 wn=qpow(3,(ysf-1)/(i<<1)); 28 for (RG int j=0;j<n;j+=i<<1) 29 for (RG int k=0,w=1,x,y;k<i;++k,w=1LL*w*wn%ysf){ 30 x=a[j+k],y=1LL*w*a[j+k+i]%ysf; 31 a[j+k]=(x+y)%ysf,a[j+k+i]=(x-y+ysf)%ysf; 32 } 33 } 34 if (f==1) return; RG int inv=qpow(n,ysf-2); 35 for (RG int i=0;i<n;++i) a[i]=1LL*a[i]*inv%ysf; 36 reverse(a+1,a+n); return; 37 } 38 39 il void solve(RG int l,RG int r){ 40 if (l==r){ vec[l].pb(l),vec[l].pb(1); return; } 41 RG int mid=(l+r)>>1; solve(l,mid),solve(mid+1,r); 42 vector<int> &a=vec[l],&b=vec[mid+1]; 43 for (len=1,lg=0;len<=r-l+1;len<<=1) ++lg; 44 for (RG int i=0;i<len;++i) 45 rev[i]=rev[i>>1]>>1|((i&1)<<(lg-1)),A[i]=B[i]=0; 46 for (RG int i=0;i<a.size();++i) A[i]=a[i]; 47 for (RG int i=0;i<b.size();++i) B[i]=b[i]; 48 NTT(A,len,1),NTT(B,len,1); 49 for (RG int i=0;i<len;++i) A[i]=1LL*A[i]*B[i]%ysf; 50 NTT(A,len,-1); for (RG int i=0;i<a.size();++i) a[i]=A[i]; 51 for (RG int i=a.size();i<=r-l+1;++i) a.pb(A[i]); return; 52 } 53 54 il int C(RG int n,RG int m){ 55 RG int res1=1,res2=1; 56 for (RG int i=1;i<=n;++i) res1=1LL*res1*i%ysf; 57 for (RG int i=1;i<=m;++i) res2=1LL*res2*i%ysf; 58 for (RG int i=1;i<=n-m;++i) res2=1LL*res2*i%ysf; 59 return 1LL*res1*qpow(res2,ysf-2)%ysf; 60 } 61 62 int main(){ 63 #ifndef ONLINE_JUDGE 64 freopen("blues.in","r",stdin); 65 freopen("blues.out","w",stdout); 66 #endif 67 cin>>n>>a>>b; if (n==1) cout<<(a==1&&b==1),exit(0); 68 if (a+b>n+1 || !a || !b) puts("0"),exit(0); solve(0,n-2); 69 cout<<1LL*vec[0][a+b-2]*C(a+b-2,a-1)%ysf; return 0; 70 }