# [BZOJ4555][TJOI2016&HEOI2016]求和(分治FFT)

## 4555: [Tjoi2016&Heoi2016]求和

Time Limit: 40 Sec  Memory Limit: 128 MB
Submit: 525  Solved: 418
[Submit][Status][Discuss]

## Description

S(i, j)表示第二类斯特林数，递推公式为:
S(i, j) = j ∗ S(i − 1, j) + S(i − 1, j − 1), 1 <= j <= i − 1。

## Output

输出f(n)。由于结果会很大，输出f(n)对998244353(7 × 17 × 223 + 1)取模的结果即可。1 ≤ n ≤ 100000

3

87

## Source

[l,mid]和[mid+1,r]卷起来怎么处理呢？平移数组变成[0,mid-l]和[mid-l+1,r-l+1]卷，次数界设为r-l+1即可。

 1 #include<cstdio>
2 #include<algorithm>
3 #define rep(i,l,r) for (int i=l; i<=r; i++)
4 typedef long long ll;
5 using namespace std;
6
7 const int N=(1<<18)+100,P=998244353,g=3;
8 int n,rev[N];
9 ll inv[N],fac[N],facinv[N],f[N],a[N],b[N];
10
11 ll ksm(ll a,ll b){
12    ll ans=1;
13    for (; b; b>>=1,a=a*a%P)
14       if (b & 1) ans=ans*a%P;
15    return ans;
16 }
17
18 void DFT(ll a[],int n,int f){
19    rep(i,0,n-1) if (i<rev[i]) swap(a[i],a[rev[i]]);
20    for (int i=1; i<n; i<<=1){
21       int wn=ksm(g,(f==1) ? (P-1)/(i<<1) : (P-1)-(P-1)/(i<<1));
22       for (int p=i<<1,j=0; j<n; j+=p){
23          int w=1;
24          for (int k=0; k<i; k++,w=1ll*w*wn%P){
25             int x=a[j+k],y=1ll*w*a[i+j+k]%P;
26             a[j+k]=(x+y)%P; a[i+j+k]=(x-y+P)%P;
27          }
28       }
29    }
30    if (f==-1){
31       int inv=ksm(n,P-2);
32       rep(i,0,n-1) a[i]=1ll*a[i]*inv%P;
33    }
34 }
35
36 void cdq(int l,int r){
37    if (l==r) return;
38    int mid=(l+r)>>1,lim=r-l+1,n=1,L=0;
39    cdq(l,mid);
40    while (n<lim) n<<=1,L++;
41    rep(i,0,n-1) rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));
42    rep(i,0,n-1) a[i]=b[i]=0;
43    rep(i,l,mid) a[i-l]=f[i];
44    rep(i,0,r-l) b[i]=facinv[i];
45    DFT(a,n,1); DFT(b,n,1);
46    rep(i,0,n-1) a[i]=a[i]*b[i]%P;
47    DFT(a,n,-1);
48    rep(i,mid+1,r) f[i]=(f[i]+2*a[i-l])%P;
49    cdq(mid+1,r);
50 }
51
52 int main(){
53    freopen("bzoj4555.in","r",stdin);
54    freopen("bzoj4555.out","w",stdout);
55    scanf("%d",&n); inv[1]=1; fac[0]=facinv[0]=1;
56    rep(i,1,n){
57       if (i!=1) inv[i]=(P-P/i)*inv[P%i]%P;
58       fac[i]=fac[i-1]*i%P;
59       facinv[i]=facinv[i-1]*inv[i]%P;
60    }
61    f[0]=1; cdq(0,n); ll ans=0;
62    rep(i,0,n) ans=(ans+f[i]*fac[i]%P)%P;
63    if (ans<0) ans+=P;
64    printf("%lld\n",ans);
65    return 0;
66 }
posted @ 2018-01-11 23:14  HocRiser  阅读(294)  评论(0编辑  收藏  举报