#pragma once
#include"src/polynomials/ntt.hpp"/**
* Author: Teetat T.
* Date: 2024-03-17
* Description: basic operations of formal power series
*/template<classmint>structFormalPowerSeries:vector<mint>{usingvector<mint>::vector;usingFPS=FormalPowerSeries;FPS&operator+=(constFPS&rhs){if(rhs.size()>this->size())this->resize(rhs.size());for(inti=0;i<rhs.size();i++)(*this)[i]+=rhs[i];return*this;}FPS&operator+=(constmint&rhs){if(this->empty())this->resize(1);(*this)[0]+=rhs;return*this;}FPS&operator-=(constFPS&rhs){if(rhs.size()>this->size())this->resize(rhs.size());for(inti=0;i<rhs.size();i++)(*this)[i]-=rhs[i];return*this;}FPS&operator-=(constmint&rhs){if(this->empty())this->resize(1);(*this)[0]-=rhs;return*this;}FPS&operator*=(constFPS&rhs){autores=NTT<mint>()(*this,rhs);return*this=FPS(res.begin(),res.end());}FPS&operator*=(constmint&rhs){for(auto&a:*this)a*=rhs;return*this;}friendFPSoperator+(FPSlhs,constFPS&rhs){returnlhs+=rhs;}friendFPSoperator+(FPSlhs,constmint&rhs){returnlhs+=rhs;}friendFPSoperator+(constmint&lhs,FPS&rhs){returnrhs+=lhs;}friendFPSoperator-(FPSlhs,constFPS&rhs){returnlhs-=rhs;}friendFPSoperator-(FPSlhs,constmint&rhs){returnlhs-=rhs;}friendFPSoperator-(constmint&lhs,FPSrhs){return-(rhs-lhs);}friendFPSoperator*(FPSlhs,constFPS&rhs){returnlhs*=rhs;}friendFPSoperator*(FPSlhs,constmint&rhs){returnlhs*=rhs;}friendFPSoperator*(constmint&lhs,FPSrhs){returnrhs*=lhs;}FPSoperator-(){return(*this)*-1;}FPSrev(){FPSres(*this);reverse(res.beign(),res.end());returnres;}FPSpre(intsz){FPSres(this->begin(),this->begin()+min((int)this->size(),sz));if(res.size()<sz)res.resize(sz);returnres;}FPSshrink(){FPSres(*this);while(!res.empty()&&res.back()==mint{})res.pop_back();returnres;}FPSoperator>>(intsz){if(this->size()<=sz)return{};FPSres(*this);res.erase(res.begin(),res.begin()+sz);returnres;}FPSoperator<<(intsz){FPSres(*this);res.insert(res.begin(),sz,mint{});returnres;}FPSdiff(){constintn=this->size();FPSres(max(0,n-1));for(inti=1;i<n;i++)res[i-1]=(*this)[i]*mint(i);returnres;}FPSintegral(){constintn=this->size();FPSres(n+1);res[0]=0;if(n>0)res[1]=1;llmod=mint::get_mod();for(inti=2;i<=n;i++)res[i]=(-res[mod%i])*(mod/i);for(inti=0;i<n;i++)res[i+1]*=(*this)[i];returnres;}minteval(constmint&x){mintres=0,w=1;for(auto&a:*this)res+=a*w,w*=x;returnres;}FPSinv(intdeg=-1){assert(!this->empty()&&(*this)[0]!=mint(0));if(deg==-1)deg=this->size();FPSres{mint(1)/(*this)[0]};for(inti=2;i>>1<deg;i<<=1){res=(res*(mint(2)-res*pre(i))).pre(i);}returnres.pre(deg);}FPSlog(intdeg=-1){assert(!this->empty()&&(*this)[0]==mint(1));if(deg==-1)deg=this->size();return(pre(deg).diff()*inv(deg)).pre(deg-1).integral();}FPSexp(intdeg=-1){assert(this->empty()||(*this)[0]==mint(0));if(deg==-1)deg=this->size();FPSres{mint(1)};for(inti=2;i>>1<deg;i<<=1){res=(res*(pre(i)-res.log(i)+mint(1))).pre(i);}returnres.pre(deg);}FPSpow(llk,intdeg=-1){constintn=this->size();if(deg==-1)deg=n;if(k==0){FPSres(deg);if(deg)res[0]=mint(1);returnres;}for(inti=0;i<n;i++){if(__int128_t(i)*k>=deg)returnFPS(deg,mint(0));if((*this)[i]==mint(0))continue;mintrev=mint(1)/(*this)[i];FPSres=(((*this*rev)>>i).log(deg)*k).exp(deg);res=((res*binpow((*this)[i],k))<<(i*k)).pre(deg);returnres;}returnFPS(deg,mint(0));}};
#line 2 "src/modular-arithmetic/binpow.hpp"
/**
* Author: Teetat T.
* Date: 2024-01-15
* Description: n-th power using divide and conquer
* Time: $O(\log b)$
*/template<classT>constexprTbinpow(Ta,llb){Tres=1;for(;b>0;b>>=1,a*=a)if(b&1)res*=a;returnres;}#line 2 "src/modular-arithmetic/montgomery-modint.hpp"
/**
* Author: Teetat T.
* Date: 2024-03-17
* Description: modular arithmetic operators using Montgomery space
*/template<uint32_tmod,uint32_troot=0>structMontgomeryModInt{usingmint=MontgomeryModInt;usingi32=int32_t;usingu32=uint32_t;usingu64=uint64_t;staticconstexpru32get_r(){u32res=1;for(i32i=0;i<5;i++)res*=2-mod*res;returnres;}staticconstu32r=get_r();staticconstu32n2=-u64(mod)%mod;static_assert(mod<(1<<30));static_assert((mod&1)==1);static_assert(r*mod==1);u32x;constexprMontgomeryModInt():x(0){}constexprMontgomeryModInt(constint64_t&v):x(reduce(u64(v%mod+mod)*n2)){}staticconstexpru32get_mod(){returnmod;}staticconstexprmintget_root(){returnmint(root);}explicitconstexproperatorint64_t()const{returnval();}staticconstexpru32reduce(constu64&v){return(v+u64(u32(v)*u32(-r))*mod)>>32;}constexpru32val()const{u32res=reduce(x);returnres>=mod?res-mod:res;}constexprmintinv()const{inta=val(),b=mod,u=1,v=0,q=0;while(b>0){q=a/b;a-=q*b;u-=q*v;swap(a,b);swap(u,v);}returnmint(u);}constexprmint&operator+=(constmint&rhs){if(i32(x+=rhs.x-2*mod)<0)x+=2*mod;return*this;}constexprmint&operator-=(constmint&rhs){if(i32(x-=rhs.x)<0)x+=2*mod;return*this;}constexprmint&operator*=(constmint&rhs){x=reduce(u64(x)*rhs.x);return*this;}constexprmint&operator/=(constmint&rhs){return*this*=rhs.inv();}constexprmint&operator++(){return*this+=mint(1);}constexprmint&operator--(){return*this-=mint(1);}constexprmintoperator++(int){mintres=*this;return*this+=mint(1),res;}constexprmintoperator--(int){mintres=*this;return*this-=mint(1),res;}constexprmintoperator-()const{returnmint()-mint(*this);};constexprmintoperator+()const{returnmint(*this);};friendconstexprmintoperator+(constmint&lhs,constmint&rhs){returnmint(lhs)+=rhs;}friendconstexprmintoperator-(constmint&lhs,constmint&rhs){returnmint(lhs)-=rhs;}friendconstexprmintoperator*(constmint&lhs,constmint&rhs){returnmint(lhs)*=rhs;}friendconstexprmintoperator/(constmint&lhs,constmint&rhs){returnmint(lhs)/=rhs;}friendconstexprbooloperator==(constmint&lhs,constmint&rhs){return(lhs.x>=mod?lhs.x-mod:lhs.x)==(rhs.x>=mod?rhs.x-mod:rhs.x);}friendconstexprbooloperator!=(constmint&lhs,constmint&rhs){return(lhs.x>=mod?lhs.x-mod:lhs.x)!=(rhs.x>=mod?rhs.x-mod:rhs.x);}friendconstexprbooloperator<(constmint&lhs,constmint&rhs){return(lhs.x>=mod?lhs.x-mod:lhs.x)<(rhs.x>=mod?rhs.x-mod:rhs.x);// for std::map}friendistream&operator>>(istream&is,mint&o){int64_tv;is>>v;o=mint(v);returnis;}friendostream&operator<<(ostream&os,constmint&o){returnos<<o.val();}};usingmint998=MontgomeryModInt<998244353,3>;usingmint107=MontgomeryModInt<1000000007>;#line 4 "src/polynomials/ntt.hpp"
/**
* Author: Teetat T.
* Description: Number Theoretic Transform
* Time: $O(N \log N)$
*/template<classmint>structNTT{usingvm=vector<mint>;staticconstexprmintroot=mint::get_root();static_assert(root!=0);staticvoidntt(vm&a){intn=a.size(),L=31-__builtin_clz(n);vmrt(n);rt[1]=1;for(intk=2,s=2;k<n;k*=2,s++){mintz[]={1,binpow(root,MOD>>s)};for(inti=k;i<2*k;i++)rt[i]=rt[i/2]*z[i&1];}vector<int>rev(n);for(inti=1;i<n;i++)rev[i]=(rev[i/2]|(i&1)<<L)/2;for(inti=1;i<n;i++)if(i<rev[i])swap(a[i],a[rev[i]]);for(intk=1;k<n;k*=2)for(inti=0;i<n;i+=2*k)for(intj=0;j<k;j++){mintz=rt[j+k]*a[i+j+k];a[i+j+k]=a[i+j]-z;a[i+j]+=z;}}staticvmconv(constvm&a,constvm&b){if(a.empty()||b.empty())return{};ints=a.size()+b.size()-1,n=1<<(32-__builtin_clz(s));mintinv=mint(n).inv();vmin1(a),in2(b),out(n);in1.resize(n),in2.resize(n);ntt(in1),ntt(in2);for(inti=0;i<n;i++)out[-i&(n-1)]=in1[i]*in2[i]*inv;ntt(out);returnvm(out.begin(),out.begin()+s);}vmoperator()(constvm&a,constvm&b){returnconv(a,b);}};#line 3 "src/polynomials/formal-power-series.hpp"
/**
* Author: Teetat T.
* Date: 2024-03-17
* Description: basic operations of formal power series
*/template<classmint>structFormalPowerSeries:vector<mint>{usingvector<mint>::vector;usingFPS=FormalPowerSeries;FPS&operator+=(constFPS&rhs){if(rhs.size()>this->size())this->resize(rhs.size());for(inti=0;i<rhs.size();i++)(*this)[i]+=rhs[i];return*this;}FPS&operator+=(constmint&rhs){if(this->empty())this->resize(1);(*this)[0]+=rhs;return*this;}FPS&operator-=(constFPS&rhs){if(rhs.size()>this->size())this->resize(rhs.size());for(inti=0;i<rhs.size();i++)(*this)[i]-=rhs[i];return*this;}FPS&operator-=(constmint&rhs){if(this->empty())this->resize(1);(*this)[0]-=rhs;return*this;}FPS&operator*=(constFPS&rhs){autores=NTT<mint>()(*this,rhs);return*this=FPS(res.begin(),res.end());}FPS&operator*=(constmint&rhs){for(auto&a:*this)a*=rhs;return*this;}friendFPSoperator+(FPSlhs,constFPS&rhs){returnlhs+=rhs;}friendFPSoperator+(FPSlhs,constmint&rhs){returnlhs+=rhs;}friendFPSoperator+(constmint&lhs,FPS&rhs){returnrhs+=lhs;}friendFPSoperator-(FPSlhs,constFPS&rhs){returnlhs-=rhs;}friendFPSoperator-(FPSlhs,constmint&rhs){returnlhs-=rhs;}friendFPSoperator-(constmint&lhs,FPSrhs){return-(rhs-lhs);}friendFPSoperator*(FPSlhs,constFPS&rhs){returnlhs*=rhs;}friendFPSoperator*(FPSlhs,constmint&rhs){returnlhs*=rhs;}friendFPSoperator*(constmint&lhs,FPSrhs){returnrhs*=lhs;}FPSoperator-(){return(*this)*-1;}FPSrev(){FPSres(*this);reverse(res.beign(),res.end());returnres;}FPSpre(intsz){FPSres(this->begin(),this->begin()+min((int)this->size(),sz));if(res.size()<sz)res.resize(sz);returnres;}FPSshrink(){FPSres(*this);while(!res.empty()&&res.back()==mint{})res.pop_back();returnres;}FPSoperator>>(intsz){if(this->size()<=sz)return{};FPSres(*this);res.erase(res.begin(),res.begin()+sz);returnres;}FPSoperator<<(intsz){FPSres(*this);res.insert(res.begin(),sz,mint{});returnres;}FPSdiff(){constintn=this->size();FPSres(max(0,n-1));for(inti=1;i<n;i++)res[i-1]=(*this)[i]*mint(i);returnres;}FPSintegral(){constintn=this->size();FPSres(n+1);res[0]=0;if(n>0)res[1]=1;llmod=mint::get_mod();for(inti=2;i<=n;i++)res[i]=(-res[mod%i])*(mod/i);for(inti=0;i<n;i++)res[i+1]*=(*this)[i];returnres;}minteval(constmint&x){mintres=0,w=1;for(auto&a:*this)res+=a*w,w*=x;returnres;}FPSinv(intdeg=-1){assert(!this->empty()&&(*this)[0]!=mint(0));if(deg==-1)deg=this->size();FPSres{mint(1)/(*this)[0]};for(inti=2;i>>1<deg;i<<=1){res=(res*(mint(2)-res*pre(i))).pre(i);}returnres.pre(deg);}FPSlog(intdeg=-1){assert(!this->empty()&&(*this)[0]==mint(1));if(deg==-1)deg=this->size();return(pre(deg).diff()*inv(deg)).pre(deg-1).integral();}FPSexp(intdeg=-1){assert(this->empty()||(*this)[0]==mint(0));if(deg==-1)deg=this->size();FPSres{mint(1)};for(inti=2;i>>1<deg;i<<=1){res=(res*(pre(i)-res.log(i)+mint(1))).pre(i);}returnres.pre(deg);}FPSpow(llk,intdeg=-1){constintn=this->size();if(deg==-1)deg=n;if(k==0){FPSres(deg);if(deg)res[0]=mint(1);returnres;}for(inti=0;i<n;i++){if(__int128_t(i)*k>=deg)returnFPS(deg,mint(0));if((*this)[i]==mint(0))continue;mintrev=mint(1)/(*this)[i];FPSres=(((*this*rev)>>i).log(deg)*k).exp(deg);res=((res*binpow((*this)[i],k))<<(i*k)).pre(deg);returnres;}returnFPS(deg,mint(0));}};