比赛 noi2017模板练习+ 评测结果 AAAAAAAAAA
题目名称 帕秋莉的超级多项式 最终得分 100
用户昵称 lemonoil 运行时间 38.565 s
代码语言 C++ 内存使用 32.64 MiB
提交时间 2017-07-18 19:36:02
显示代码纯文本
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
#define maxn 530010ul
int G,P=119*(1<<23)+1;
namespace polynomial{
    int ksm(int p,int k,int mod){
        int ans=1;
        while(k){
            if(k&1) ans=1ll*ans*p%mod;
            k>>=1ll,p=1ll*p*p%mod;
        }
        return ans;
    }
   void ntt(int *a,int n,int flag){
        for(int i=0,j=0;i<n;i++){
            if(i>j) std::swap(a[i],a[j]);
            for(int t=n>>1;(j^=t)<t;t>>=1);
        }
        int w,wn,u,t;
        for(int m=2;m<=n;m<<=1){
            wn=ksm(G,flag==1?(P-1)/m:(P-1-(P-1)/m),P),w=1ll;
            for(int i=0;i<n;i+=m,w=1ll) for(int k=0,p=m>>1;k<p;k++,w=1ll*w*wn%P)
                t=1ll*w*a[i+k+p]%P,u=a[i+k],a[i+k]=(u+t)%P,a[i+k+p]=(u-t)%P;
        }
        if(flag==-1){
            int inv=ksm(n,P-2,P);
            for(int i=0;i<n;i++) a[i]=1ll*a[i]*inv%P;
        }
        return;
    }
    void poly_derivative(int *poly,int *der,int n){
        poly[n]=0;
        for(int i=0;i<n;i++) der[i]=1ll*(i+1)*poly[i+1]%P;
        return;
    }
    void poly_integrate(int *poly,int n){
        static int tmp[maxn];tmp[0]=0;
        for(int i=0;i<n;i++) tmp[i+1]=1ll*poly[i]*ksm(i+1,P-2,P)%P;
        for(int i=0;i<n;i++) poly[i]=(tmp[i]%P+P)%P;
        return;
    }
    void poly_inverse(int *f,int *g,int n){
        static int tmp[maxn];
        if(n==1){g[0]=ksm(f[0],P-2,P);return;}
        poly_inverse(f,g,n>>1);
        memcpy(tmp,f,sizeof(f[0])*n);
        memset(tmp+n,0,sizeof(f[0])*n);
        ntt(tmp,n<<1,1),ntt(g,n<<1,1);
        for(int i=0;i<(n<<1);i++) tmp[i]=1ll*g[i]*(2ll-1ll*g[i]*tmp[i]%P)%P;
        ntt(tmp,n<<1,-1);
        for(int i=0;i<n;i++) g[i]=tmp[i];
        memset(g+n,0,sizeof(g[0])*n);
        return;
    }
    void poly_sqrt(int *f,int *g,int n){
        static int tmp[maxn],ginv[maxn];
        if(n==1){g[0]=(int)sqrt(f[0]);return;}
        int inv2=ksm(2,P-2,P);
        poly_sqrt(f,g,n>>1);
        memset(ginv,0,sizeof(ginv[0])*n);
        poly_inverse(g,ginv,n);
        memcpy(tmp,f,sizeof(f[0])*n);
        memset(tmp+n,0,sizeof(f[0])*n);
        ntt(tmp,n<<1,1),ntt(g,n<<1,1),ntt(ginv,n<<1,1);
        for(int i=0;i<(n<<1);i++) tmp[i]=1ll*inv2*(g[i]+1ll*tmp[i]*ginv[i]%P)%P;
        ntt(tmp,n<<1,-1);
        for(int i=0;i<n;i++) g[i]=tmp[i];
        memset(g+n,0,sizeof(g[0])*n);
        return;
    }
    void poly_ln(int *poly,int *ln,int n){
        static int der[maxn],inv[maxn];
        memset(inv,0,sizeof(inv[0])*(n<<1));
        memset(der,0,sizeof(der[0])*(n<<1));
        poly_inverse(poly,inv,n);
        poly_derivative(poly,der,n);
        ntt(der,n<<1,1),ntt(inv,n<<1,1);
        for(int i=0;i<(n<<1);i++)
            ln[i]=1ll*der[i]*inv[i]%P;
        ntt(ln,n<<1,-1);
        poly_integrate(ln,n);
        memset(ln+n,0,sizeof(ln[0])*n);
        memset(inv,0,sizeof(inv[0])*(n<<1));
        memset(der,0,sizeof(der[0])*(n<<1));
        return;
    }
    void poly_exp(int *poly,int *exp,int n){
        static int tmp[maxn];
        if(n==1){exp[0]=1;return;}
        poly_exp(poly,exp,n>>1);
        memset(tmp,0,sizeof(tmp[0])*n<<1);
        poly_ln(exp,tmp,n);
        for(int i=0;i<n;i++) tmp[i]=((i==0)+P-tmp[i]+poly[i])%P;
        ntt(tmp,n<<1,1),ntt(exp,n<<1,1);
        for(int i=0;i<(n<<1);i++) exp[i]=1ll*exp[i]*tmp[i]%P;
        ntt(exp,n<<1,-1);
        for(int i=0;i<n;i++) ((exp[i]%=P)+=P)%=P;
        memset(exp+n,0,sizeof(exp[0])*n);
        return;
    }
    void poly_pow(int *poly,int n,int k){
        static int ln[maxn],exp[maxn];
        poly_ln(poly,ln,n);
        for(int i=0;i<n;i++) poly[i]=1ll*k*ln[i]%P;
        poly_exp(poly,exp,n);
        for(int i=0;i<n;i++) poly[i]=exp[i];
        return;
    }
    bool primitive_root_judge(int x,int p){
        for(int i=2;i*i<=p;i++) if((p-1)%i==0&&ksm(x,(p-1)/i,p)==1)
            return false;
        return true;
    }
    int primitive_root(int p){
        if(p==2) return 1;
        int ans=2;
        for(;!primitive_root_judge(ans,p);++ans);
        return ans;
    }
}
void read(int &x){
    x=0;int c=getchar();
    while(c<'0'||c>'9') c=getchar();
    for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    return;
}
int n,k,len,F[maxn],sqrtF[maxn],lnv_sqrt[maxn],exp_[maxn],inv2[maxn],ln2[maxn],G_[maxn];
int main(){
	freopen("polynomial.in","r",stdin);
	freopen("polynomial.out","w",stdout);
	G=polynomial::primitive_root(P);
	read(n),read(k);
	for(int i=0;i<n;i++) read(F[i]);
	for(len=1;len<=n;len<<=1);
	polynomial::poly_sqrt(F,sqrtF,len);
	polynomial::poly_inverse(sqrtF,lnv_sqrt,len);
	polynomial::poly_integrate(lnv_sqrt,len);
	polynomial::poly_exp(lnv_sqrt,exp_,len);
	polynomial::poly_inverse(exp_,inv2,len);
	(inv2[0]+=1)%=P;
	polynomial::poly_ln(inv2,ln2,len);
	(ln2[0]+=1)%=P;
	polynomial::poly_pow(ln2,len,k);
	polynomial::poly_derivative(ln2,G_,n);
	for(int i=0;i<n;i++) printf("%d ",(G_[i]%P+P)%P);
    return 0;
}