#pragma once
/**
* 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 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>;