多項式全家桶
阿新 • • 發佈:2020-12-19
#include<bits/stdc++.h> using namespace std; const int mod=998244353,G=3,ivG=332748118,N=4e6+5; inline int in() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();} return x*f; } struct poly { vector<int>v; inline int&operator[](int x) { while(x>=v.size())v.push_back(0); return v[x]; } inline void pre(int x,int lim) { int t=min(lim,(int)v.size()); for(int i=x;i<t;++i)v[i]=0; } }; namespace Math { int inv[N],pif; inline int add(int x,int y){x+=y;return x>=mod?x-mod:x;} inline int dec(int x,int y){x-=y;return x<0?x+mod:x;} inline int mll(int x,int y){return 1ll*x*y%mod;} struct pt { int x,y; pt(int _x=0,int _y=0){x=_x,y=_y;} inline pt operator*(const pt&rhs) { return pt(add(mll(x,rhs.x),mll(mll(y,rhs.y),pif)),add(mll(x,rhs.y),mll(y,rhs.x))); } }; inline int qpow(int x,int y) { int ans=1; for(;y;y>>=1,x=mll(x,x))(y&1)&&(ans=mll(ans,x)); return ans; } inline pt qpow(pt x,int y) { pt ans=pt(1,0); for(;y;y>>=1,x=x*x)if(y&1)ans=ans*x; return ans; } inline void pre(int n) { inv[1]=1; for(int i=2;i<=n;++i)inv[i]=mod-mll(mod/i,inv[mod%i]); } inline bool ck(int x){return qpow(x,(mod-1)>>1)==mod-1;} inline int solve(int x) { int ans=0; if(mod==2)return x; if(!x)return 0; else if(qpow(x,(mod-1)>>1)==mod-1)return -1; int a=rand()%mod; while(!a||!ck(dec(mll(a,a),x)))a=rand()%mod; pif=dec(mll(a,a),x); ans=qpow(pt(a,1),(mod+1)>>1).x; return min(ans,mod-ans); } } using namespace Math; namespace Bas { int rev[N],wn[N]; inline void ntt(int lim,poly&f,bool tp) { for(int i=0;i<lim;++i)if(i<rev[i])swap(f[i],f[rev[i]]); for(int mid=1;mid<lim;mid<<=1) { int sw=qpow(tp?ivG:G,(mod-1)/(mid<<1)); wn[0]=1;for(int i=1;i<mid;++i)wn[i]=mll(wn[i-1],sw); for(int len=mid<<1,p=0;p+len-1<lim;p+=len) for(int k=0;k<mid;++k) { int x=f[p+k],y=1ll*wn[k]*f[p+mid+k]%mod; f[p+k]=add(x,y),f[p+mid+k]=dec(x,y); } } } inline poly mul(int n,int m,poly f,poly g) { int lim=1,l=0;while(lim<n+m)lim<<=1,++l; for(int i=0;i<lim;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1)); f.pre(n,lim),g.pre(m,lim); ntt(lim,f,0),ntt(lim,g,0); for(int i=0;i<lim;++i)f[i]=mll(f[i],g[i]); ntt(lim,f,1);int iv=qpow(lim,mod-2); for(int i=0;i<lim;++i)f[i]=mll(f[i],iv); return f; } inline void igl(int n,poly&f) { for(int i=n-1;i;--i)f[i]=mll(f[i-1],inv[i]);f[0]=0; } inline void diff(int n,poly&f) { for(int i=0;i<n-1;++i)f[i]=mll(f[i+1],i+1);f[n-1]=0; } inline void rv(int n,poly&f){reverse(f.v.begin(),f.v.begin()+n);} inline void read(int n,poly&f){for(int i=0;i<n;++i)f[i]=in();} inline void print(int n,poly f){for(int i=0;i<n;++i)printf("%d ",f[i]);puts("");} } using namespace Bas; namespace Poly { poly ginv(int n,poly f) { if(n==1){poly g;g[0]=qpow(f[0],mod-2);return g;} poly g=ginv(n+1>>1,f),h,p=g; int lim=1,l=0;while(lim<n+n)lim<<=1,++l; for(int i=0;i<lim;++i)rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1)); f.pre(n,lim),p.pre(n,lim); ntt(lim,f,0),ntt(lim,p,0); for(int i=0;i<lim;++i)f[i]=mll(f[i],mll(p[i],p[i])); ntt(lim,f,1);int iv=qpow(lim,mod-2); for(int i=0;i<n;++i)h[i]=dec(add(g[i],g[i]),mll(f[i],iv)); return h; } inline poly ln(int n,poly f) { poly g=ginv(n,f),h;diff(n,f); h=mul(n,n,f,g);igl(n,h); return h; } poly exp(int n,poly f) { if(n==1){poly g;g[0]=1;return g;} poly g=exp(n+1>>1,f); poly h=ln(n,g); for(int i=0;i<n;++i)h[i]=add(dec(0,h[i]),f[i]); h[0]=add(h[0],1); return mul(n,n,g,h); } inline poly div(int n,int m,poly f,poly g) { rv(n,f),rv(m,g); g=ginv(n-m+1,g); poly q=mul(n,n-m+1,f,g); rv(n-m+1,q);return q; } inline poly sqr(int n,poly f) { if(n==1){poly g;g[0]=solve(f[0]);return g;} poly g=sqr(n+1>>1,f),h,ivg; ivg=ginv(n,g),h=mul(n,n,g,g); int iv=qpow(2,mod-2); for(int i=0;i<n;++i)ivg[i]=mll(iv,ivg[i]); for(int i=0;i<n;++i)h[i]=dec(h[i],f[i]); h=mul(n,n,h,ivg); for(int i=0;i<n;++i)h[i]=dec(g[i],h[i]); return h; } inline poly fsp(int n,int k1,int k2,poly f) { int u,k;poly ans; for(u=0;u<n&&!f[u];++u);k=qpow(f[u],k2); if(1ll*u*k2>=n)return ans; int iv=qpow(f[u],mod-2); for(int i=u;i<n;++i)f[i]=mll(f[i],iv); for(int i=0,j=u;j<n;++i,++j)ans[i]=f[j]; ans=ln(n,ans); for(int i=0;i<n;++i)ans[i]=mll(ans[i],k1); ans=exp(n,ans); for(int i=0;i<u*k2;++i)f[i]=0; for(int i=u*k2,j=0;i<n;++i,++j)f[i]=mll(ans[j],k); return f; } } using namespace Poly; char ch[N]; int main() { int n,k1=0,k2=0,k3=0;scanf("%d",&n);pre(n); scanf("%s",ch+1);int len=strlen(ch+1); poly f;read(n,f); for(int i=1;i<=len;++i) { k1=add(mll(10,k1),ch[i]^48), k2=(10ll*k2%(mod-1)+(ch[i]^48))%(mod-1); if(k1>n&&!f[0]) { for(int i=0;i<n;++i)printf("0 "); return 0; } } print(n,fsp(n,k1,k2,f));//主函式對應的是多項式快速冪加強版:即不保證a0=1 return 0; }