[COGS2189]帕秋莉的超级多项式(多项式全家桶)

版权声明:转载需要注明哦QwQ,地址:http://blog.csdn.net/effervescence。 https://blog.csdn.net/Effervescence/article/details/82633861

原题传送门

Code

  直接上模板全套就好辣!(跑得还挺快,17.33s,现在在rk10)

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
bool Finish_read;
template<class T>inline void read(T &x){Finish_read=0;x=0;int f=1;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}while(isdigit(ch))x=x*10+ch-'0',ch=getchar();x*=f;Finish_read=1;}
template<class T>inline void print(T x){if(x/10!=0)print(x/10);putchar(x%10+'0');}
template<class T>inline void writeln(T x){if(x<0)putchar('-');x=abs(x);print(x);putchar('\n');}
template<class T>inline void write(T x){if(x<0)putchar('-');x=abs(x);print(x);}
/*================Header Template==============*/
const int mod=998244353,inv2=(mod+1)>>1;
namespace {
    inline int Add(const int &x,const int &y) {
        int res=x+y;
        if(res>=mod)
            res-=mod;
        return res;
    }
    inline int Sub(const int &x,const int &y) {
        int res=x-y;
        if(res<0)
            res+=mod;
        return res;
    }
    inline int Mul(const int &x,const int &y) {
        return 1ll*x*y%mod;
    }
    inline int Pow(int x,int y=mod-2) {
        int res=1;
        while(y) {
            if(y&1)
                res=1ll*res*x%mod;
            x=1ll*x*x%mod;
            y>>=1;
        }
        return res;
    }
}
const int fmaxn=18,Fmaxn=(1<<fmaxn)+5,G=3;
int nxtl[Fmaxn],nxtlim[Fmaxn],inv[Fmaxn];
namespace Poly {
    static int root[fmaxn][Fmaxn],mx,rev[Fmaxn];
    inline void Rev(int l) {
        rev[0]=0;
        for(int i=1;i<(1<<l);++i)
            rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
    }
    inline void DFT(vector<int>&a,int bit) {
        if(mx<bit) {
            for(int i=mx;i<bit;++i) {
                int len=1<<i,w0=Pow(G,(mod-1)/(len<<1)),w=1;
                for(int j=0;j<len;++j)
                    root[i][j]=w,w=Mul(w,w0);
            }
            mx=bit;
        }
        for(int i=1;i<1<<bit;++i)
            if(i<rev[i])
                swap(a[i],a[rev[i]]);
        for(int i=0,len=1;i<bit;++i,len<<=1)
            for(int j=0;j<(1<<bit);j+=(len<<1))
                for(int k=0;k<len;++k) {
                    int x=a[j+k],y=Mul(a[j+k+len],root[i][k]);
                    a[j+k]=Add(x,y),a[j+k+len]=Sub(x,y);
                }
    }
    inline void IDFT(vector<int>&a,int bit) {
        int len=(1<<bit),inv=Pow(len);
        reverse(a.begin()+1,a.end());
        DFT(a,bit);
        for(int i=0;i<len;++i)
            a[i]=Mul(a[i],inv);
    }
    inline void FFT(vector<int>a,vector<int>b,vector<int>&c) {
        int la=a.size(),lb=b.size(),lc=la+lb-1,l=nxtl[lc],lim=nxtlim[lc];
        a.resize(lim),b.resize(lim),c.resize(lim);
        Rev(l),DFT(a,l),DFT(b,l);
        for(int i=0;i<lim;++i)
            c[i]=Mul(a[i],b[i]);
        IDFT(c,l);
        c.resize(lc);
    }
    inline void Inv(vector<int>f,vector<int>&g,int len) {
        int lim=nxtlim[len];
        f.resize(lim),g.resize(lim);
        g[0]=Pow(f[0]);
        for(int i=2,p=1;i<=lim;i<<=1,++p) {
            vector<int>h(i<<1),l(i<<1),o(i<<1);
            for(int j=0;j<i;++j)
                h[j]=f[j];
            for(int j=0;j<i>>1;++j)
                l[j]=g[j];
            Rev(p+1),DFT(h,p+1),DFT(l,p+1);
            for(int j=0;j<i<<1;++j)
                o[j]=Mul(h[j],Mul(l[j],l[j]));
            IDFT(o,p+1);
            for(int j=0;j<i;++j)
                g[j]=Sub(Mul(2,g[j]),o[j]);
        }
        g.resize(len);
    }
    inline void Ln(vector<int>f,vector<int>&g,int len) {
        vector<int>h(len,0);
        for(int i=1;i<len;++i)
            h[i-1]=Mul(f[i],i);
        h[len-1]=0;
        Inv(f,g,len);
        FFT(g,h,g);
        for(int i=len-1;i;--i)
            g[i]=Mul(g[i-1],::inv[i]);
        g[0]=0;
        g.resize(len);
    }
    inline void Exp(vector<int>f,vector<int>&g,int len,int init) {
        int lim=nxtlim[len];
        f.resize(lim),g.resize(lim);
        if(init)
            g[0]=1;
        for(int i=2,p=1;i<=lim;i<<=1,++p) {
            vector<int>h(i<<1),l,o(i<<1,0);
            for(int j=0;j<i>>1;++j)
                h[j]=g[j];
            Ln(h,l,i);
            for(int j=0;j<i;++j)
                l[j]=Sub(f[j]+(!j),l[j]),l.push_back(0);
            Rev(p+1),DFT(h,p+1),DFT(l,p+1);
            for(int j=0;j<i<<1;++j)
                o[j]=Mul(h[j],l[j]);
            IDFT(o,p+1);
            for(int j=0;j<i;++j)
                g[j]=o[j];
        }
        g.resize(len);
    }
    inline void Pow(vector<int>f,vector<int>&g,int len,ll k) {
        vector<int>h;
        Ln(f,h,len);
        int o=k%mod;
        for(int i=0;i<len;++i)
            h[i]=Mul(h[i],o);
        g.push_back(::Pow(f[0],(int)(k%(mod-1))));
        Exp(h,g,len,0);
    }
    inline void Sqrt(vector<int>f,vector<int>&g,int len) {
        g.push_back((int)sqrt(f[0]));
        int lim=nxtlim[len];
        for(int i=2,p=1;i<=lim;i<<=1,++p) {
            vector<int>h(i),l,o(i<<1,0);
            g.resize(i<<1);
            for(int j=0;j<i;++j)
                h[j]=g[j];
            Inv(h,l,i);
            l.resize(i<<1);
            for(int j=0;j<min(i,(int)f.size());++j)
                o[j]=f[j];
            Rev(p+1),DFT(g,p+1),DFT(l,p+1),DFT(o,p+1);
            for(int j=0;j<i<<1;++j)
                o[j]=Mul(Add(g[j],Mul(l[j],o[j])),inv2);
            IDFT(o,p+1);
            for(int j=0;j<i;++j)
                g[j]=o[j];
            g.resize(i);
        }
        g.resize(len);
    }
}
vector<int>a,b,c;
int n,m;
inline void Getmul() {
    a.clear(),b.clear();
    read(n),read(m);
    for(int i=0,x;i<=n;++i)
        read(x),a.push_back(x);
    for(int i=0,x;i<=m;++i)
        read(x),b.push_back(x);
    Poly::FFT(a,b,c);
    for(int i=0;i<(int)c.size();++i)
        printf("%d ",c[i]);
}
inline void Getinv() {
    a.clear();
    read(n);
    for(int i=0,x;i<n;++i)
        read(x),a.push_back(x);
    Poly::Inv(a,b,n);
    for(int i=0;i<n;++i)
        printf("%d ",b[i]);
}
inline void Getln() {
    a.clear();
    read(n);
    for(int i=0,x;i<n;++i)
        read(x),a.push_back(x);
    Poly::Ln(a,b,n);
    for(int i=0;i<n;++i)
        printf("%d ",b[i]);
}
inline void Getexp() {
    a.clear();
    read(n);
    for(int i=0,x;i<n;++i)
        read(x),a.push_back(x);
    Poly::Exp(a,b,n,1);
    for(int i=0;i<n;++i)
        printf("%d ",b[i]);
}
inline void Getpow() {
    a.clear();ll p;
    read(n),read(p);
    for(int i=0,x;i<n;++i)
        read(x),a.push_back(x);
    Poly::Pow(a,b,n,p);
    for(int i=0;i<n;++i)
        printf("%d ",b[i]);
}
inline void Getsqrt() {
    a.clear();
    read(n);
    for(int i=0,x;i<n;++i)
        read(x),a.push_back(x);
    Poly::Sqrt(a,b,n);
    for(int i=0;i<n;++i)
        printf("%d ",b[i]);
}
int main() {
    freopen("polynomial.in","r",stdin);
    freopen("polynomial.out","w",stdout);
    nxtl[1]=0,nxtlim[1]=1,inv[1]=1;
    for(int i=1;i<Fmaxn-1;++i) {
        nxtl[i+1]=nxtl[i],nxtlim[i+1]=nxtlim[i];
        if(i==(i&-i))
            ++nxtl[i+1],nxtlim[i+1]<<=1;
    }
    for(int i=2;i<Fmaxn;++i)
        inv[i]=Mul(inv[mod%i],(mod-mod/i));
    // Getmul();
    // Getinv();
    // Getln();
    // Getexp();
    // Getpow();
    // Getsqrt();
    read(n);ll p;read(p);
    for(int i=0,x;i<n;++i)
        read(x),a.push_back(x);
    Poly::Sqrt(a,b,n);
    Poly::Inv(b,c,n);
    for(int i=n-1;i;--i)
        c[i]=Mul(c[i-1],inv[i]);
    c[0]=0;
    b.clear();
    Poly::Exp(c,b,n,1);
    c.clear();
    Poly::Inv(b,c,n);
    ++c[0];
    b.clear();
    Poly::Ln(c,b,n);
    ++b[0];
    c.clear();
    Poly::Pow(b,c,n,p);
    for(int i=1;i<n;++i)
        c[i-1]=Mul(c[i],i);
    c[n-1]=0;
    for(int i=0;i<n;++i)
        printf("%d ",c[i]);
    puts("");
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Effervescence/article/details/82633861