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 }

 

posted @ 2018-04-12 11:16  wfj_2048  阅读(461)  评论(4编辑  收藏  举报