luoguP4238 【模板】多项式求逆 NTT

Code:

#include <bits/stdc++.h>
#define maxn 300000
#define G 3 
#define ll long long 
#define P 998244352
#define MOD 998244353     
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;
namespace FFT{
    int rev[maxn];  
    ll Pow(ll a,ll k){
        ll base=1;
        while(k){
            if(k&1) base=(base*a)%MOD; 
            a=(a*a)%MOD; 
            k>>=1; 
        }
        return base%MOD; 
    }
    void NTT(ll *a,int len,int opt){
        for(int i=0;i<len;++i)
            if(i<rev[i]) swap(a[i],a[rev[i]]);  
        for(int i=1;i<len;i<<=1){
            ll wn=Pow(G,(opt*P/(i<<1)+P))%P;
            int step=i<<1; 
            for(int j=0;j<len;j+=step){
                ll w=1; 
                for(int k=0;k<i;++k,w=(1ll*w*wn)%MOD){
                    ll x=a[j+k];
                    ll y=1ll*w*a[j+k+i]%MOD; 
                    a[j+k]=(x+y)%MOD; 
                    a[j+k+i]=(x-y+MOD)%MOD; 
                }
            }
        }
        if(opt==-1){
            ll r=Pow(len,MOD-2);
            for(int i=0;i<len;++i)
                a[i]=1ll*a[i]*r%MOD; 
        }
    } 
    void calrev(int lim,int l){
        for(int i=1;i<lim;++i) 
            rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1)); 
    }
    ll add(ll a,ll b){
        a+=b; 
        a%=MOD; 
        return a; 
    }
    long long  X[maxn],Y[maxn]; 
    void mul(ll *x,ll *y,int lim){
        memset(X,0,sizeof(X)); 
        memset(Y,0,sizeof(Y)); 
        for(int i=0;i<(lim>>1);++i) 
            X[i]=x[i],Y[i]=y[i]; 
        NTT(X,lim,1);
        NTT(Y,lim,1); 
        for(int i=0;i<lim;++i) 
            X[i]=(ll)X[i]*Y[i]%MOD; 
        NTT(X,lim,-1); 
        for(int i=0;i<lim;++i) 
            x[i]=X[i]; 
    }
}; 
ll A[maxn],B[3][maxn],C[maxn],D[maxn]; 
int main(){
    //setIO("input"); 
    int n; 
    scanf("%d",&n); 
    --n; 
    for(int i=0;i<=n;++i) 
        scanf("%lld",&A[i]);  
    int cur=0;
    B[cur][0]=FFT::Pow(A[0],MOD-2); 
    int bas=1,lim=2,len=1; 
    FFT::calrev(lim,len); 
    while(bas<=(n<<1)){
        cur^=1; 
        memset(B[cur],0,sizeof(B[cur])); 
        for(int i=0;i<bas;++i) 
            B[cur][i]=FFT::add(B[cur^1][i]<<1,0); 
        FFT::mul(B[cur^1],B[cur^1],lim); 
        FFT::mul(B[cur^1],A,lim); 
        for(int i=0;i<bas;++i) 
            B[cur][i]=FFT::add(B[cur][i],MOD-B[cur^1][i]); 
        bas<<=1,lim<<=1,++len; 
        if(bas<=(n<<1)) 
            FFT::calrev(lim,len); 
            
    }
    for(int i=0;i<=n;++i) 
        printf("%lld ",B[cur][i]); 
    return 0; 
}

  

猜你喜欢

转载自www.cnblogs.com/guangheli/p/10712753.html