[ 斯特林數 NTT ] [ Tjoi2016&Heoi2016 ] BZOJ4555 求和

題解

#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=400010;
const int P=998244353;
int a[N],b[N],c[N];
int w[2][N];
int r[N];
int inv[N],si[N];
int k,n,m,M,l;
int Ans;
int Pow(int x,int y) {
    int Ans=1;
    for(;y;y>>=1,x=1ll*x*x%P)
        if(y&1)Ans=1ll*Ans*x%P;
    return Ans;
}
void init(int n) {
    inv[0]=inv[1]=si[0]=si[1]=1;
    for(int i=2;i<=n;i++)
        inv[i]=1ll*inv[P%i]*(P-P/i)%P,si[i]=1ll*si[i-1]*inv[i]%P;
}
void Pre(int n) {
    w[0][0]=w[1][0]=1;
    int g=Pow(3,(P-1)/n);
    for(int i=1;i<n;i++) w[0][i]=1ll*w[0][i-1]*g%P;
    for(int i=1;i<n;i++) w[1][i]=w[0][n-i];
}
void DFT(int* a,int n,int d) {
    for(int i=0;i<n;i++)
        if(r[i]>i)swap(a[i],a[r[i]]);
    for(int i=1;i<n;i<<=1) {
        for(int j=0;j<n;j+=i<<1) {
            for(int k=0;k<i;k++) {
                int x=a[j+k],y=1ll*a[j+k+i]*w[d][n/(i<<1)*k]%P;
                a[j+k]=(x+y)%P;a[j+k+i]=(x-y)%P;
            }
        }
    }
    if(!d){
        int inv=Pow(n,P-2);
        for(int i=0;i<n;i++) a[i]=1ll*a[i]*inv%P;
    }
}
void NTT(int* a,int* b,int* c,int n) {
    for(int i=0;i<n;i++) r[i]=(r[i>>1]>>1)|((i&1)<<l-1);
    DFT(a,n,1);DFT(b,n,1);
    for(int i=0;i<n;i++) c[i]=1ll*a[i]*b[i]%P;
    DFT(c,n,0);
}
int main() {
    scanf("%d",&n);
    init(n);
    for(int i=0,t=1;i<=n;i++) {
        a[i]=t*si[i]%P;t*=-1;
        b[i]=i==1?n+1:1ll*(Pow(i,n+1)-1)*si[i]%P*Pow(i-1,P-2)%P;
    }
    for(M=1;M<=(n<<1);M<<=1,l++);
    Pre(M);NTT(a,b,c,M);
    for(int i=0,t=1,T=1;i<=n;i++) {
        Ans=(Ans+1ll*t*T%P*c[i]%P)%P;
        t=(t<<1)%P;T=1ll*T*(i+1)%P;
    }
    cout<<(Ans+P)%P<<endl;
    return 0;
}
發佈了288 篇原創文章 · 獲贊 104 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章