#pragma once
#include"library/formalpowerseries/Base.hpp"
#include"library/math/ModularSqrt.hpp"
#include<optional>// Computes the square root of a formal power series f.// Returns std::nullopt if the square root does not exist.template<typenameFPS>std::optional<FPS>sqrt(FPSf){usingT=typenameFPS::value_type;f.shrink();if(f.size()==0){returnFPS(0);}intd=0;while(d<f.size()&&f[d]==0){d++;}if(d==f.size()){returnFPS(0);}if(d%2!=0){returnstd::nullopt;}f>>=d;std::optional<T>s0=mod_sqrt(f[0]);if(!s0){returnstd::nullopt;}FPSres(1,*s0);intn=1;constexprintMX=FPS::max_size;while(n<MX){n<<=1;res=(res+f.pre(n)*res.inv(n))/2;}res.strict(MX);res<<=(d/2);returnres;}
#line 1 "library/util/Valarray.hpp"
#include<functional>
#include<ranges>
#include<vector>template<typenameT>structValarray:std::vector<T>{usingstd::vector<T>::vector;// コンストラクタ継承Valarray(conststd::vector<T>&v):std::vector<T>(v.begin(),v.end()){}private:template<typenameOp>Valarray&apply_inplace(constValarray&other,Opop){if(this->size()<other.size())this->resize(other.size(),T(0));for(auto[a,b]:std::views::zip(*this,other))a=op(a,b);return*this;}public:Valarray&operator+=(constValarray&other){returnapply_inplace(other,std::plus<>());}Valarray&operator-=(constValarray&other){returnapply_inplace(other,std::minus<>());}Valarray&operator*=(constValarray&other){returnapply_inplace(other,std::multiplies<>());}Valarray&operator/=(constValarray&other){returnapply_inplace(other,std::divides<>());}friendValarrayoperator+(Valarraya,constValarray&b){returna+=b;}friendValarrayoperator-(Valarraya,constValarray&b){returna-=b;}friendValarrayoperator*(Valarraya,constValarray&b){returna*=b;}friendValarrayoperator/(Valarraya,constValarray&b){returna/=b;}Valarrayoperator-()const{Valarrayg=*this;for(T&a:g)a=-a;returng;}};#line 3 "library/formalpowerseries/Base.hpp"
template<typenameT,intMX>structFormalPowerSeries:Valarray<T>{usingFPS=FormalPowerSeries;staticconstexprintmax_size=MX;usingValarray<T>::Valarray;usingValarray<T>::size;usingValarray<T>::resize;usingValarray<T>::at;usingValarray<T>::begin;usingValarray<T>::end;usingValarray<T>::back;usingValarray<T>::pop_back;usingvalue_type=T;voidstrict(intn){if(size()>n)resize(n);shrink();}voidshrink(){while(size()andback()==0)pop_back();}FormalPowerSeries()=default;FormalPowerSeries(conststd::vector<T>&f):Valarray<T>(f){strict(MX);shrink();}staticFPSunit(){return{1};}staticFPSx(){return{0,1};}#pragma region operator
FPSoperator-()const{returnFPS(Valarray<T>::operator-());}FPS&operator+=(constFPS&g){Valarray<T>::operator+=(g);shrink();return*this;}FPSoperator+(constFPS&g)const{returnFPS(*this)+=g;}FPS&operator-=(constFPS&g){Valarray<T>::operator-=(g);shrink();return*this;}FPSoperator-(constFPS&g)const{returnFPS(*this)-=g;}FPS&operator+=(constT&a){if(!size())resize(1);at(0)+=a;return*this;}FPSoperator+(constT&a)const{returnFPS(*this)+=a;}friendFPSoperator+(constT&a,constFPS&f){returnf+a;}FPS&operator-=(constT&a){if(!size())resize(1);at(0)-=a;return*this;}FPSoperator-(constT&a){returnFPS(*this)-=a;}friendFPSoperator-(constT&a,constFPS&f){returna+(-f);}FPSoperator*(constFPS&g)const{returnFPS(convolution(*this,g));}FPS&operator*=(constFPS&g){return(*this)=(*this)*g;}FPS&operator*=(constT&a){for(size_ti=0;i<size();i++)at(i)*=a;return*this;}FPSoperator*(constT&a)const{returnFPS(*this)*=a;}friendFPSoperator*(constT&a,constFPS&f){returnf*a;}FPSoperator/(constFPS&g)const{return(*this)*g.inv();}FPS&operator/=(constFPS&g){return(*this)=(*this)/g;}FPS&operator/=(constT&a){return*this*=a.inv();}FPSoperator/(constT&a){returnFPS(*this)/=a;}FPS&operator<<=(constintd){if(d>=MX)return*this=FPS(0);resize(std::min(MX,int(size())+d));for(inti=int(size())-1-d;i>=0;i--)at(i+d)=at(i);for(inti=d-1;i>=0;i--)at(i)=0;return*this;}FPSoperator<<(constintd)const{returnFPS(*this)<<=d;}FPS&operator>>=(constintd){if(d>=size())return*this=FPS(0);for(size_ti=d;i<size();i++)at(i-d)=at(i);strict(int(size())-d);return*this;}FPSoperator>>(constintd)const{returnFPS(*this)>>=d;}#pragma endregion operator
FPSpre(intn)const{if(size()<=n)return*this;returnFPS(Valarray<T>(this->begin(),this->begin()+n));}// 最小の非ゼロ次数(すべて 0 のときは size())を返すintorder()const{for(inti=0;i<int(size());i++){if(at(i)!=0)returni;}returnint(size());}FPSinv(intSZ=MX)const{assert(size()andat(0)!=0);FPSres={at(0).inv()};for(intn=1;n<SZ;n<<=1){res*=(2-this->pre(n<<1)*res);res.strict(n<<1);}res.strict(SZ);returnres;}// *this = f_1 + f_2 x^n ⇒ [*this←f_1, return f_2]FPSseparate(intn){if(size()<=n)returnFPS(0);FPSf_2(size()-n);for(size_ti=n;i<size();i++)f_2[i-n]=at(i);strict(n);returnf_2;}Toperator()(Ta)const{Tres=0,b=1;for(size_ti=0;i<size();i++,b*=a)res+=at(i)*b;returnres;}};#line 2 "library/math/ExtraGCD.hpp"
usingll=longlong;std::pair<ll,ll>ext_gcd(lla,llb){if(b==0)return{1,0};auto[X,Y]=ext_gcd(b,a%b);// bX + (a%b)Y = gcd(a,b)// a%b = a - b(a/b)// ∴ aY + b(X-(a/b)Y) = gcd(a,b)llx=Y,y=X-(a/b)*Y;return{x,y};}#line 3 "library/mod/Modint.hpp"
template<typenameT,TMOD=998244353>structMint{inlinestaticconstexprTmod=MOD;Tv;Mint():v(0){}Mint(signedv):v(v){}Mint(longlongt){v=t%MOD;if(v<0)v+=MOD;}staticMintraw(intv){Mintx;x.v=v;returnx;}Mintpow(longlongk)const{Mintres(1),tmp(v);while(k){if(k&1)res*=tmp;tmp*=tmp;k>>=1;}returnres;}staticMintadd_identity(){returnMint(0);}staticMintmul_identity(){returnMint(1);}// Mint inv()const{return pow(MOD-2);}Mintinv()const{returnMint(ext_gcd(v,mod).first);}Mint&operator+=(Minta){v+=a.v;if(v>=MOD)v-=MOD;return*this;}Mint&operator-=(Minta){v+=MOD-a.v;if(v>=MOD)v-=MOD;return*this;}Mint&operator*=(Minta){v=1LL*v*a.v%MOD;return*this;}Mint&operator/=(Minta){return(*this)*=a.inv();}Mintoperator+(Minta)const{returnMint(v)+=a;}Mintoperator-(Minta)const{returnMint(v)-=a;}Mintoperator*(Minta)const{returnMint(v)*=a;}Mintoperator/(Minta)const{returnMint(v)/=a;}#define FRIEND(op) \
friend Mint operator op(int a, Mint b) { return Mint(a) op b; }
FRIEND(+);FRIEND(-);FRIEND(*);FRIEND(/);#undef FRIEND
Mintoperator+()const{return*this;}Mintoperator-()const{returnv?Mint(MOD-v):Mint(v);}booloperator==(constMinta)const{returnv==a.v;}booloperator!=(constMinta)const{returnv!=a.v;}staticMintcomb(longlongn,intk){Mintnum(1),dom(1);for(inti=0;i<k;i++){num*=Mint(n-i);dom*=Mint(i+1);}returnnum/dom;}friendstd::ostream&operator<<(std::ostream&os,constMint&m){os<<m.v;returnos;}friendstd::istream&operator>>(std::istream&is,Mint&m){is>>m.v;m.v%=MOD;if(m.v<0)m.v+=MOD;returnis;}};#line 3 "library/math/ModularSqrt.hpp"
#include<optional>
#include<random>
#include<chrono>template<typenameT,TMOD>boolis_quadratic_residue(Mint<T,MOD>a){if(a==0)returntrue;returna.pow((MOD-1)/2)==1;}template<typenameT,TMOD>std::optional<Mint<T,MOD>>mod_sqrt(Mint<T,MOD>a){if(a==0)returnMint<T,MOD>(0);if(MOD==2)returna;if(!is_quadratic_residue(a))returnstd::nullopt;if(MOD%4==3){returna.pow((MOD+1)/4);}// Tonelli-Shankslonglongs=0,q=MOD-1;while(q%2==0){q/=2;s++;}// Find a non-quadratic residue zstd::mt19937_64rng(std::chrono::steady_clock::now().time_since_epoch().count());Mint<T,MOD>z;do{z=rng()%MOD;}while(is_quadratic_residue(z));longlongm=s;Mint<T,MOD>c=z.pow(q);Mint<T,MOD>t=a.pow(q);Mint<T,MOD>r=a.pow((q+1)/2);while(t!=1){if(t==0)returnMint<T,MOD>(0);longlongi=0;Mint<T,MOD>temp=t;while(temp!=1){temp*=temp;i++;if(i==m)returnstd::nullopt;// Should not happen for quadratic residues}Mint<T,MOD>b=c.pow(1LL<<(m-i-1));m=i;c=b*b;t*=c;r*=b;}returnr;}#line 5 "library/formalpowerseries/Sqrt.hpp"
// Computes the square root of a formal power series f.// Returns std::nullopt if the square root does not exist.template<typenameFPS>std::optional<FPS>sqrt(FPSf){usingT=typenameFPS::value_type;f.shrink();if(f.size()==0){returnFPS(0);}intd=0;while(d<f.size()&&f[d]==0){d++;}if(d==f.size()){returnFPS(0);}if(d%2!=0){returnstd::nullopt;}f>>=d;std::optional<T>s0=mod_sqrt(f[0]);if(!s0){returnstd::nullopt;}FPSres(1,*s0);intn=1;constexprintMX=FPS::max_size;while(n<MX){n<<=1;res=(res+f.pre(n)*res.inv(n))/2;}res.strict(MX);res<<=(d/2);returnres;}