[HEOI2016/TJOI2016]求和

NTT卷积

#include<cstdio>
#include<algorithm>
#include<iostream>
const int mod = 998244353,g=3;
const int maxn = 400100;
typedef long long ll;
inline int pow(int a,int b,int ans=1){
    for(;b;b>>=1,a=ll(a)*a%mod)
        if(b&1)ans=ll(ans)*a%mod;
    return ans;
}
inline int inv(int a){return pow(a,mod-2);}
inline void reduce(int&x){x+=x>>31&mod;}
int rev[maxn],wn[maxn],lim;
inline void init(int len){
    lim=*wn=1;
    while(lim<len)lim<<=1;
    for(int i=1;i<lim;++i)rev[i]=rev[i>>1]>>1|(i%2*lim/2);
}
inline void fst(int*a,int type){
    for(int i=1;i<lim;++i)if(rev[i]>i)std::swap(a[rev[i]],a[i]);
    for(int mid=1;mid<lim;mid<<=1){
        const int W=pow(g,mod/mid/2);
        for(int i=1;i<mid;++i)wn[i]=ll(wn[i-1])*W%mod;
        for(int j=0;j<lim;j+=mid+mid)
            for(int*A=a+j,*B=A+mid,*w=wn;w!=wn+mid;++A,++B,++w){
                const int x=*A,y=ll(*B)**w%mod;
                reduce(*A=x+y-mod),reduce(*B=x-y);
            }
    }
    if(!type){
        for(int i=0,lm=inv(lim);i<lim;++i)a[i]=ll(a[i])*lm%mod;
        std::reverse(a+1,a+lim);
    }
}
int a[maxn],b[maxn];
int _[maxn];
int n;
int main(){
    std::ios::sync_with_stdio(false),std::cin.tie(0);
    std::cin >> n;
    _[0]=1;
    for(int i=1;i<=n;++i)_[i]=ll(_[i-1])*i%mod;
    for(int i=0;i<=n;++i)a[i]=i&1?mod-inv(_[i]):inv(_[i]);
    b[1]=n+1,b[0]=1;
    for(int i=2;i<=n;++i)b[i]=ll(pow(i,n+1)-1)*inv(ll(i-1)*_[i]%mod)%mod;
    init(n+1<<1);
    fst(a,1),fst(b,1);
    for(int i=0;i<lim;++i)a[i]=ll(a[i])*b[i]%mod;
    fst(a,0);
    int ans=0;
    for(int i=0;i<=n;++i)reduce(ans+=ll(pow(2,i))*_[i]%mod*a[i]%mod-mod);
    std::cout << ans << '
';
}
原文地址:https://www.cnblogs.com/skip1978/p/10348574.html