ZTL — 数学 — 多项式 — 板子

namespace Poly{
    int limit, l, r[maxn];
    
    //the modulo numbers and related, may be changed due to the problems.
    #define mod 998244353
    #define G 3
    #define Gi 332748118
    const int INV2 = 499122177;
    const int INV3 = 332748118;
     
    inline ll ksm(ll x, ll y){
        ll ret = 1;
        while(y){if(y & 1) ret = ret * x % mod; y >>= 1; x = x*x%mod;}
        return ret;
    }
    inline ll inv(ll x){return ksm(x,mod-2);}
    inline void NTT(int *a, int type){
        for(int i = 0; i < limit; ++i) if(i < r[i]) swap(a[i], a[r[i]]);
        for(int mid = 1; mid < limit; mid <<= 1){
            ll wn = ksm(type==1 ? G : Gi, (mod-1)/(mid<<1));
            for(int i = 0; i < limit; i += (mid<<1)){
                ll w = 1;
                for(int j = 0; j < mid; ++j, w = w*wn%mod){
                    int x = a[j+i], y = w*a[j+i+mid] % mod;
                    a[j+i] = (x+y) % mod;
                    a[j+i+mid] = (x-y+mod) % mod;
                }
            }
        }
        if(type == 1) return;
        ll INV = inv(limit);
        for(int i = 0; i < limit; ++i) a[i] = 1LL * a[i] * INV % mod;
    }
    
    int C[maxn];    
    void Inverse(int *a, int *ret, int deg){//use C
        if(deg == 1){ ret[0] = inv(a[0]); return; }
        Inverse(a, ret, (deg+1)>>1);
        
        l = 0, limit = 1;
        while(limit < (deg<<1)) limit <<= 1, ++l;
        for(int i = 1; i < limit; ++i) r[i] = ((r[i>>1]>>1) | ((1&i) << (l-1)));
        
        for(int i = 0; i < deg; ++i) C[i] = a[i];
        for(int i = deg; i < limit; ++i) C[i] = 0;
        NTT(C,1);  NTT(ret,1);
        
        for(int i = 0; i < limit; ++i) ret[i] = 1LL*(2-1LL*C[i]*ret[i]%mod+mod)%mod*ret[i]%mod;
        NTT(ret,-1);
        for(int i = deg; i < limit; ++i) ret[i] = 0;
    }
    
    inline void Derivation(int *a, int *ret, int len){
        for(int i = 1; i < len; ++i) ret[i-1] = 1ll*i*a[i]%mod; 
        ret[len-1] = 0;
    } 
    inline void Integral(int *a, int *ret, int len){
        for(int i = 1; i < len; ++i) ret[i] = 1ll*a[i-1]*inv(i)%mod; 
        ret[0] = 0;
    }
    
    int A[maxn], B[maxn];
    inline void Ln(int *a, int *ret, int len){//use A, B
        memset(A,0,sizeof(A)); memset(B,0,sizeof(B));
        Derivation(a, A, len); Inverse(a, B, len);
        
        limit = 1, l = 0;
        while(limit < (len<<1)) limit<<=1, ++l;
        for(int i = 1; i < limit; ++i) r[i] = ((r[i>>1]>>1) | ((1&i) << (l-1)));
        
        NTT(A,1); NTT(B,1);
        for(int i = 0; i < limit; ++i) A[i] = A[i]*B[i]%mod;
        NTT(A,-1);
        
        Integral(A,ret,len);
    }
    
    
    int D[maxn], E[maxn];
    void Exp(int *a, int *ret, int len){//use D, E
        if(len == 1) {ret[0] = 1; return;}
        Exp(a, ret, (len+1)>>1);
        
        l = 0, limit = 1;
        while(limit < (len<<1)) limit <<= 1, ++l;
        for(int i = 1; i < limit; ++i) r[i] = ((r[i>>1]>>1) | ((1&i) << (l-1)));
        
        memset(D, 0, sizeof(D)); memset(E, 0, sizeof(E));
        Ln(ret, D, len);
        for(int i = 0; i < len; ++i) E[i] = a[i];
        
        NTT(D,1); NTT(E,1); NTT(ret,1);
        for(int i = 0; i < limit; ++i) ret[i] = (1ll-D[i]+E[i]+mod) * ret[i] % mod;
        NTT(ret,-1);
        for(int i = len; i < limit; ++i) ret[i] = 0;
    }
    
    
    int H[maxn], I[maxn];//F, G留作他用 
    void Sqrt(int *a, int *ret, int len){//use H, I, 只资瓷常数项为1的
        if(len == 1) {ret[0] = 1; return;}
        Sqrt(a, ret, (len+1)>>1);
        
        l = 0, limit = 1;
        while(limit < (len<<1)) limit <<= 1, ++l;
        for(int i = 1; i < limit; ++i) r[i] = ((r[i>>1]>>1) | ((1&i) << (l-1)));
        
        memset(H, 0, sizeof(H)); memset(I, 0, sizeof(I));
        for(int i = 0; i < len; ++i) H[i] = a[i];
        
        Inverse(ret, I, len);
        
        NTT(H,1); NTT(I,1);
        for(int i = 0; i < limit; ++i) I[i] = 1ll*H[i]*I[i] % mod;
        NTT(I,-1);
        
        for(int i = 0; i < len; ++i) ret[i] = 1ll * (ret[i]+I[i]) * INV2 % mod;
    }
}
posted @ 2020-11-24 20:31  zimindaada  阅读(68)  评论(0编辑  收藏  举报