#ifndef _FEISTDLIB_POLY_#define _FEISTDLIB_POLY_/* * This file is part of the fstdlib project. * Version: Build v0.0.2 * You can check for details at https://github.com/FNatsuka/fstdlib */#include<algorithm>#include<cmath>#include<cstdio>#include<vector>namespacefstdlib{typedeflonglongll;intmod=998244353,grt=3;classpoly{private:std::vector<int>data;voidout(void){for(inti=0;i<(int)data.size();++i)printf("%d ",data[i]);puts("");}public:poly(std::size_tlen=std::size_t(0)){data=std::vector<int>(len);}poly(conststd::vector<int>&b){data=b;}poly(constpoly&b){data=b.data;}voidresize(std::size_tlen,intval=0){data.resize(len,val);}std::size_tsize(void)const{returndata.size();}voidclear(void){data.clear();}#if __cplusplus >= 201103Lvoidshrink_to_fit(void){data.shrink_to_fit();}#endifint&operator[](std::size_tb){returndata[b];}constint&operator[](std::size_tb)const{returndata[b];}polyoperator*(constpoly&h)const;polyoperator*=(constpoly&h);polyoperator*(constint&h)const;polyoperator*=(constint&h);polyoperator+(constpoly&h)const;polyoperator+=(constpoly&h);polyoperator-(constpoly&h)const;polyoperator-=(constpoly&h);polyoperator<<(conststd::size_t&b)const;polyoperator<<=(conststd::size_t&b);polyoperator>>(conststd::size_t&b)const;polyoperator>>=(conststd::size_t&b);polyoperator/(constint&h)const;polyoperator/=(constint&h);polyoperator==(constpoly&h)const;polyoperator!=(constpoly&h)const;polyoperator+(constint&h)const;polyoperator+=(constint&h);polyinv(void)const;polyinv(constint&h)const;friendpolysqrt(constpoly&h);friendpolylog(constpoly&h);friendpolyexp(constpoly&h);};intqpow(inta,intb,intp=mod){intres=1;while(b){if(b&1)res=(ll)res*a%p;a=(ll)a*a%p,b>>=1;}returnres;}std::vector<int>rev;voiddft_for_module(std::vector<int>&f,intn,intb){staticstd::vector<int>w;w.resize(n);for(inti=0;i<n;++i)if(i<rev[i])std::swap(f[i],f[rev[i]]);for(inti=2;i<=n;i<<=1){w[0]=1,w[1]=qpow(grt,(mod-1)/i);if(b==-1)w[1]=qpow(w[1],mod-2);for(intj=2;j<i/2;++j)w[j]=(ll)w[j-1]*w[1]%mod;for(intj=0;j<n;j+=i)for(intk=0;k<i/2;++k){intp=f[j+k],q=(ll)f[j+k+i/2]*w[k]%mod;f[j+k]=(p+q)%mod,f[j+k+i/2]=(p-q+mod)%mod;}}}polypoly::operator*(constpoly&h)const{intN=1;while(N<(int)(size()+h.size()-1))N<<=1;std::vector<int>f(this->data),g(h.data);f.resize(N),g.resize(N);rev.resize(N);for(inti=0;i<N;++i)rev[i]=(rev[i>>1]>>1)|(i&1?N>>1:0);dft_for_module(f,N,1),dft_for_module(g,N,1);for(inti=0;i<N;++i)f[i]=(ll)f[i]*g[i]%mod;dft_for_module(f,N,-1),f.resize(size()+h.size()-1);for(inti=0,inv=qpow(N,mod-2);i<(int)f.size();++i)f[i]=(ll)f[i]*inv%mod;returnf;}polypoly::operator*=(constpoly&h){return*this=*this*h;}polypoly::operator*(constint&h)const{std::vector<int>f(this->data);for(inti=0;i<(int)f.size();++i)f[i]=(ll)f[i]*h%mod;returnf;}polypoly::operator*=(constint&h){for(inti=0;i<(int)size();++i)data[i]=(ll)data[i]*h%mod;return*this;}polypoly::operator+(constpoly&h)const{std::vector<int>f(this->data);if(f.size()<h.size())f.resize(h.size());for(inti=0;i<(int)h.size();++i)f[i]=(f[i]+h[i])%mod;returnf;}polypoly::operator+=(constpoly&h){std::vector<int>&f=this->data;if(f.size()<h.size())f.resize(h.size());for(inti=0;i<(int)h.size();++i)f[i]=(f[i]+h[i])%mod;returnf;}polypoly::operator-(constpoly&h)const{std::vector<int>f(this->data);if(f.size()<h.size())f.resize(h.size());for(inti=0;i<(int)h.size();++i)f[i]=(f[i]-h[i]+mod)%mod;returnf;}polypoly::operator-=(constpoly&h){std::vector<int>&f=this->data;if(f.size()<h.size())f.resize(h.size());for(inti=0;i<(int)h.size();++i)f[i]=(f[i]-h[i]+mod)%mod;returnf;}polypoly::operator<<(conststd::size_t&b)const{std::vector<int>f(size()+b);for(inti=0;i<(int)size();++i)f[i+b]=data[i];returnf;}polypoly::operator<<=(conststd::size_t&b){return*this=(*this)<<b;}polypoly::operator>>(conststd::size_t&b)const{std::vector<int>f(size()-b);for(inti=0;i<(int)f.size();++i)f[i]=data[i+b];returnf;}polypoly::operator>>=(conststd::size_t&b){return*this=(*this)>>b;}polypoly::operator/(constint&h)const{std::vector<int>f(this->data);intinv=qpow(h,mod-2);for(inti=0;i<(int)f.size();++i)f[i]=(ll)f[i]*inv%mod;returnf;}polypoly::operator/=(constint&h){intinv=qpow(h,mod-2);for(inti=0;i<(int)data.size();++i)data[i]=(ll)data[i]*inv%mod;return*this;}polypoly::inv(void)const{intN=1;while(N<(int)(size()+size()-1))N<<=1;std::vector<int>f(N),g(N),d(this->data);d.resize(N),f[0]=qpow(d[0],mod-2);for(intw=2;w<N;w<<=1){for(inti=0;i<w;++i)g[i]=d[i];rev.resize(w<<1);for(inti=0;i<w*2;++i)rev[i]=(rev[i>>1]>>1)|(i&1?w:0);dft_for_module(f,w<<1,1),dft_for_module(g,w<<1,1);for(inti=0;i<w*2;++i)f[i]=(ll)f[i]*(2+mod-(ll)f[i]*g[i]%mod)%mod;dft_for_module(f,w<<1,-1);for(inti=0,inv=qpow(w<<1,mod-2);i<w;++i)f[i]=(ll)f[i]*inv%mod;for(inti=w;i<w*2;++i)f[i]=0;}f.resize(size());returnf;}polypoly::operator==(constpoly&h)const{if(size()!=h.size())return0;for(inti=0;i<(int)size();++i)if(data[i]!=h[i])return0;return1;}polypoly::operator!=(constpoly&h)const{if(size()!=h.size())return1;for(inti=0;i<(int)size();++i)if(data[i]!=h[i])return1;return0;}polypoly::operator+(constint&h)const{polyf(this->data);f[0]=(f[0]+h)%mod;returnf;}polypoly::operator+=(constint&h){return*this=(*this)+h;}polypoly::inv(constint&h)const{polyf(*this);f.resize(h);returnf.inv();}intmodsqrt(inth,intp=mod){return1;}polysqrt(constpoly&h){intN=1;while(N<(int)(h.size()+h.size()-1))N<<=1;polyf(N),g(N),d(h);d.resize(N),f[0]=modsqrt(d[0]);for(intw=2;w<N;w<<=1){g.resize(w);for(inti=0;i<w;++i)g[i]=d[i];f=(f+f.inv(w)*g)/2;f.resize(w);}f.resize(h.size());returnf;}polylog(constpoly&h){polyf(h);for(inti=1;i<(int)f.size();++i)f[i-1]=(ll)f[i]*i%mod;f[f.size()-1]=0,f=f*h.inv(),f.resize(h.size());for(inti=(int)f.size()-1;i>0;--i)f[i]=(ll)f[i-1]*qpow(i,mod-2)%mod;f[0]=0;returnf;}polyexp(constpoly&h){intN=1;while(N<(int)(h.size()+h.size()-1))N<<=1;polyf(N),g(N),d(h);f[0]=1,d.resize(N);for(intw=2;w<N;w<<=1){f.resize(w),g.resize(w);for(inti=0;i<w;++i)g[i]=d[i];f=f*(g+1-log(f));f.resize(w);}f.resize(h.size());returnf;}structcomp{longdoublex,y;comp(longdouble_x=0,longdouble_y=0):x(_x),y(_y){}compoperator*(constcomp&b)const{returncomp(x*b.x-y*b.y,x*b.y+y*b.x);}compoperator+(constcomp&b)const{returncomp(x+b.x,y+b.y);}compoperator-(constcomp&b)const{returncomp(x-b.x,y-b.y);}compconj(void){returncomp(x,-y);}};constintEPS=1e-9;template<typenameFLOAT_T>FLOAT_Tfabs(constFLOAT_T&x){returnx>0?x:-x;}template<typenameFLOAT_T>FLOAT_Tsin(constFLOAT_T&x,constlongdouble&EPS=fstdlib::EPS){FLOAT_Tres=0,delt=x;intd=0;while(fabs(delt)>EPS){res+=delt,++d;delt*=-x*x/((2*d)*(2*d+1));}returnres;}template<typenameFLOAT_T>FLOAT_Tcos(constFLOAT_T&x,constlongdouble&EPS=fstdlib::EPS){FLOAT_Tres=0,delt=1;intd=0;while(fabs(delt)>EPS){res+=delt,++d;delt*=-x*x/((2*d)*(2*d-1));}returnres;}constlongdoublePI=std::acos((longdouble)(-1));voiddft_for_complex(std::vector<comp>&f,intn,intb){staticstd::vector<comp>w;w.resize(n);for(inti=0;i<n;++i)if(i<rev[i])std::swap(f[i],f[rev[i]]);for(inti=2;i<=n;i<<=1){w[0]=comp(1,0),w[1]=comp(cos(2*PI/i),b*sin(2*PI/i));for(intj=2;j<i/2;++j)w[j]=w[j-1]*w[1];for(intj=0;j<n;j+=i)for(intk=0;k<i/2;++k){compp=f[j+k],q=f[j+k+i/2]*w[k];f[j+k]=p+q,f[j+k+i/2]=p-q;}}}classarbitrary_module_poly{private:std::vector<int>data;intconstruct_element(intD,llx,lly,llz)const{x%=mod,y%=mod,z%=mod;return((ll)D*D*x%mod+(ll)D*y%mod+z)%mod;}public:intmod;arbitrary_module_poly(std::size_tlen=std::size_t(0),intmodule_value=1e9+7){mod=module_value;data=std::vector<int>(len);}arbitrary_module_poly(conststd::vector<int>&b,intmodule_value=1e9+7){mod=module_value;data=b;}arbitrary_module_poly(constarbitrary_module_poly&b){mod=b.mod;data=b.data;}voidresize(std::size_tlen,constint&val=0){data.resize(len,val);}std::size_tsize(void)const{returndata.size();}voidclear(void){data.clear();}#if __cplusplus >= 201103Lvoidshrink_to_fit(void){data.shrink_to_fit();}#endifint&operator[](std::size_tb){returndata[b];}constint&operator[](std::size_tb)const{returndata[b];}arbitrary_module_polyoperator*(constarbitrary_module_poly&h)const;arbitrary_module_polyoperator*=(constarbitrary_module_poly&h);arbitrary_module_polyoperator*(constint&h)const;arbitrary_module_polyoperator*=(constint&h);arbitrary_module_polyoperator+(constarbitrary_module_poly&h)const;arbitrary_module_polyoperator+=(constarbitrary_module_poly&h);arbitrary_module_polyoperator-(constarbitrary_module_poly&h)const;arbitrary_module_polyoperator-=(constarbitrary_module_poly&h);arbitrary_module_polyoperator<<(conststd::size_t&b)const;arbitrary_module_polyoperator<<=(conststd::size_t&b);arbitrary_module_polyoperator>>(conststd::size_t&b)const;arbitrary_module_polyoperator>>=(conststd::size_t&b);arbitrary_module_polyoperator/(constint&h)const;arbitrary_module_polyoperator/=(constint&h);arbitrary_module_polyoperator==(constarbitrary_module_poly&h)const;arbitrary_module_polyoperator!=(constarbitrary_module_poly&h)const;arbitrary_module_polyinv(void)const;arbitrary_module_polyinv(constint&h)const;friendarbitrary_module_polysqrt(constarbitrary_module_poly&h);friendarbitrary_module_polylog(constarbitrary_module_poly&h);};arbitrary_module_polyarbitrary_module_poly::operator*(constarbitrary_module_poly&h)const{intN=1;while(N<(int)(size()+h.size()-1))N<<=1;std::vector<comp>f(N),g(N),p(N),q(N);constintD=std::sqrt(mod);for(inti=0;i<(int)size();++i)f[i].x=data[i]/D,f[i].y=data[i]%D;for(inti=0;i<(int)h.size();++i)g[i].x=h[i]/D,g[i].y=h[i]%D;rev.resize(N);for(inti=0;i<N;++i)rev[i]=(rev[i>>1]>>1)|(i&1?N>>1:0);dft_for_complex(f,N,1),dft_for_complex(g,N,1);for(inti=0;i<N;++i){p[i]=(f[i]+f[(N-i)%N].conj())*comp(0.50,0)*g[i];q[i]=(f[i]-f[(N-i)%N].conj())*comp(0,-0.5)*g[i];}dft_for_complex(p,N,-1),dft_for_complex(q,N,-1);std::vector<int>r(size()+h.size()-1);for(inti=0;i<(int)r.size();++i)r[i]=construct_element(D,p[i].x/N+0.5,(p[i].y+q[i].x)/N+0.5,q[i].y/N+0.5);returnarbitrary_module_poly(r,mod);}arbitrary_module_polyarbitrary_module_poly::operator*=(constarbitrary_module_poly&h){return*this=*this*h;}arbitrary_module_polyarbitrary_module_poly::operator*(constint&h)const{std::vector<int>f(this->data);for(inti=0;i<(int)f.size();++i)f[i]=(ll)f[i]*h%mod;returnarbitrary_module_poly(f,mod);}arbitrary_module_polyarbitrary_module_poly::operator*=(constint&h){for(inti=0;i<(int)size();++i)data[i]=(ll)data[i]*h%mod;return*this;}arbitrary_module_polyarbitrary_module_poly::operator+(constarbitrary_module_poly&h)const{std::vector<int>f(this->data);if(f.size()<h.size())f.resize(h.size());for(inti=0;i<(int)h.size();++i)f[i]=(f[i]+h[i])%mod;returnarbitrary_module_poly(f,mod);}arbitrary_module_polyarbitrary_module_poly::operator+=(constarbitrary_module_poly&h){if(size()<h.size())resize(h.size());for(inti=0;i<(int)h.size();++i)data[i]=(data[i]+h[i])%mod;return*this;}arbitrary_module_polyarbitrary_module_poly::operator-(constarbitrary_module_poly&h)const{std::vector<int>f(this->data);if(f.size()<h.size())f.resize(h.size());for(inti=0;i<(int)h.size();++i)f[i]=(f[i]+mod-h[i])%mod;returnarbitrary_module_poly(f,mod);}arbitrary_module_polyarbitrary_module_poly::operator-=(constarbitrary_module_poly&h){if(size()<h.size())resize(h.size());for(inti=0;i<(int)h.size();++i)data[i]=(data[i]+mod-h[i])%mod;return*this;}arbitrary_module_polyarbitrary_module_poly::operator<<(conststd::size_t&b)const{std::vector<int>f(size()+b);for(inti=0;i<(int)size();++i)f[i+b]=data[i];returnarbitrary_module_poly(f,mod);}arbitrary_module_polyarbitrary_module_poly::operator<<=(conststd::size_t&b){return*this=(*this)<<b;}arbitrary_module_polyarbitrary_module_poly::operator>>(conststd::size_t&b)const{std::vector<int>f(size()-b);for(inti=0;i<(int)f.size();++i)f[i]=data[i+b];returnarbitrary_module_poly(f,mod);}arbitrary_module_polyarbitrary_module_poly::operator>>=(conststd::size_t&b){return*this=(*this)>>b;}arbitrary_module_polyarbitrary_module_poly::inv(void)const{intN=1;while(N<(int)(size()+size()-1))N<<=1;arbitrary_module_polyf(1,mod),g(N,mod),h(*this),f2(1,mod);f[0]=qpow(data[0],mod-2,mod),h.resize(N),f2[0]=2;for(intw=2;w<N;w<<=1){g.resize(w);for(inti=0;i<w;++i)g[i]=h[i];f=f*(f*g-f2)*(mod-1);f.resize(w);}f.resize(size());returnf;}arbitrary_module_polyarbitrary_module_poly::inv(constint&h)const{arbitrary_module_polyf(*this);f.resize(h);returnf.inv();}arbitrary_module_polyarbitrary_module_poly::operator/(constint&h)const{intinv=qpow(h,mod-2,mod);std::vector<int>f(this->data);for(inti=0;i<(int)f.size();++i)f[i]=(ll)f[i]*inv%mod;returnarbitrary_module_poly(f,mod);}arbitrary_module_polyarbitrary_module_poly::operator/=(constint&h){intinv=qpow(h,mod-2,mod);for(inti=0;i<(int)size();++i)data[i]=(ll)data[i]*inv%mod;return*this;}arbitrary_module_polyarbitrary_module_poly::operator==(constarbitrary_module_poly&h)const{if(size()!=h.size()||mod!=h.mod)return0;for(inti=0;i<(int)size();++i)if(data[i]!=h[i])return0;return1;}arbitrary_module_polyarbitrary_module_poly::operator!=(constarbitrary_module_poly&h)const{if(size()!=h.size()||mod!=h.mod)return1;for(inti=0;i<(int)size();++i)if(data[i]!=h[i])return1;return0;}arbitrary_module_polysqrt(constarbitrary_module_poly&h){intN=1;while(N<(int)(h.size()+h.size()-1))N<<=1;arbitrary_module_polyf(1,mod),g(N,mod),d(h);f[0]=modsqrt(h[0],mod),d.resize(N);for(intw=2;w<N;w<<=1){g.resize(w);for(inti=0;i<w;++i)g[i]=d[i];f=(f+f.inv(w)*g)/2;f.resize(w);}f.resize(h.size());returnf;}arbitrary_module_polylog(constarbitrary_module_poly&h){arbitrary_module_polyf(h);for(inti=1;i<(int)f.size();++i)f[i-1]=(ll)f[i]*i%f.mod;f[f.size()-1]=0,f=f*h.inv(),f.resize(h.size());for(inti=(int)f.size()-1;i>0;--i)f[i]=(ll)f[i-1]*qpow(i,f.mod-2,f.mod)%f.mod;f[0]=0;returnf;}typedefarbitrary_module_polym_poly;}// namespace fstdlib#endif