形式的冪級数
(give_us_tmp/fps.cpp)
Code
/**
* @brief 形式的冪級数
*
* verified with :https://judge.yosupo.jp/problem/frequency_table_of_tree_distance
* submission :https://judge.yosupo.jp/submission/28303
*
*/
template<typename T,typename F>
struct fps_base:vector<T>{
using std::vector<T>::vector;
using P=fps_base<T,F>;
F op;
fps_base(F op=F()):op(op){}
P operator +(T x)const{return P(*this)+=x;}
P operator -(T x)const{return P(*this)-=x;}
P operator *(T x)const{return P(*this)*=x;}
P operator /(T x)const{return P(*this)/=x;}
P operator <<(int x){return P(*this)<<=x;}
P operator >>(int x){return P(*this)>>=x;}
P operator +(const P& x)const{return P(*this)+=x;}
P operator -(const P& x)const{return P(*this)-=x;}
P operator -()const{return P(1,T(0))-=P(*this);}
P operator *(const P& x)const{return P(*this)*=x;}
P operator /(const P& x)const{return P(*this)/=x;}
P operator %(const P& x)const{return P(*this)%=x;}
bool operator ==(P x){
return shrink()==x.shrink();
}
P &operator +=(T x){
if(this->size()==0)return *this=P{x};
(*this)[0]+=x;
return *this;
}
P &operator -=(T x){
if(this->size()==0)return *this=P{-x};
(*this)[0]+=x;
return *this;
}
P &operator *=(T x){
rep(i,0,this->size())(*this)[i]*=x;
return *this;
}
P &operator /=(T x){
return *this*=T(1)/x;
}
P &operator <<=(int x){
P ret(x,T(0));
ret.insert(ret.end(),this->begin(),this->end());
return *this=ret;
}
P &operator >>=(int x){
if((int)this->size()<=x)return *this=P();
P ret;
ret.insert(ret.end(),this->begin()+x,this->end());
return (*this)=ret;
}
P &operator +=(const P& x){
if(this->size()<x.size())this->resize(x.size(),T(0));
rep(i,0,x.size())(*this)[i]+=x[i];
return *this;
}
P &operator -=(const P& x){
if(this->size()<x.size())this->resize(x.size(),T(0));
rep(i,0,x.size())(*this)[i]-=x[i];
return *this;
}
P &operator *=(const P& x){
return *this=op(*this,x);
}
P &operator /=(P x){
if(this->size()<x.size()){this->clear();return *this;}
int n=this->size()-x.size()+1;
return *this=(rev().pre(n)*x.rev().inv(n)).pre(n).rev(n);
}
P &operator %=(const P& x){
return (*this)-=(*this)/x*x;
}
P& shrink(){while(this->size()&&this->back()==T(0))this->pop_back();return *this;}
P pre(int sz)const{
return P(this->begin(),this->begin()+min<int>(this->size(),sz));
}
P rev(int deg=-1){
P ret(*this);
if(deg!=-1)ret.resize(deg,T(0));
reverse(all(ret));
return ret;
}
P inv(int deg=-1){
assert((*this)[0]!=T(0));
const int n=deg==-1?this->size():deg;
P ret({T(1)/(*this)[0]});
for(int i=1;i<n;i<<=1){
ret*=(-ret*pre(i<<1)+2).pre(i<<1);
}
return ret.pre(n);
}
P diff(){
if((int)this->size()<=1)return P();
P ret(*this);
rep(i,0,ret.size())ret[i]*=i;
return ret>>1;
}
P integral(){
P ret(*this);
rep(i,0,ret.size())ret[i]/=i+1;
return ret<<1;
}
P log(int deg=-1){
assert((*this)[0]==T(1));
int n=deg==-1?this->size():deg;
return (diff()*inv(n)).pre(n-1).integral();
}
P exp(int deg=-1){
assert((*this)[0]==T(0));
int n=deg==-1?this->size():deg;
P ret({T(1)});
for(int i=1;i<n;i<<=1){
ret=ret*(pre(i<<1)+1-ret.log(i<<1)).pre(i<<1);
}
return ret.pre(n);
}
P pow(int c,int deg=-1){
const int n=deg==-1?this->size():deg;
long long i=0;
P ret(*static_cast<P*>(this));
while(i!=(int)this->size()&&ret[i]==0)i++;
if(i==(int)this->size())return P(n,0);
if(i*c>=n)return P(n,0);
T k=ret[i];
return ((((ret>>i)/k).log()*c).exp()*(k.pow(c))<<(i*c)).pre(n);
}
template<typename G>
P sqrt(int deg=-1,G sq=G()){
const int n=deg==-1?this->size():deg;
int tmp=0;
while((*this)[tmp]==T(0))tmp++;
if(tmp&1)return {};
if(n-tmp/2<=0)return P(n,0);
if(tmp){
return ((*this>>tmp).sqrt(n-tmp/2)<<(tmp/2)).resize(n,T(0));
}else{
P ret({T(1)});
for(int i=1;i<n;i<<=1){
ret=(ret+pre(i<<1)*ret.inv(i<<1)).pre(i<<1)/T(2);
}
return ret.pre(n);
}
}
};
struct __F__{template<typename T>T operator()(T s,T t){auto tmp=mul(s,t);return *static_cast<T*>(&tmp);}};
template<typename T>
using fps=fps_base<T,__F__>;
#line 1 "give_us_tmp/fps.cpp"
/**
* @brief 形式的冪級数
*
* verified with :https://judge.yosupo.jp/problem/frequency_table_of_tree_distance
* submission :https://judge.yosupo.jp/submission/28303
*
*/
template<typename T,typename F>
struct fps_base:vector<T>{
using std::vector<T>::vector;
using P=fps_base<T,F>;
F op;
fps_base(F op=F()):op(op){}
P operator +(T x)const{return P(*this)+=x;}
P operator -(T x)const{return P(*this)-=x;}
P operator *(T x)const{return P(*this)*=x;}
P operator /(T x)const{return P(*this)/=x;}
P operator <<(int x){return P(*this)<<=x;}
P operator >>(int x){return P(*this)>>=x;}
P operator +(const P& x)const{return P(*this)+=x;}
P operator -(const P& x)const{return P(*this)-=x;}
P operator -()const{return P(1,T(0))-=P(*this);}
P operator *(const P& x)const{return P(*this)*=x;}
P operator /(const P& x)const{return P(*this)/=x;}
P operator %(const P& x)const{return P(*this)%=x;}
bool operator ==(P x){
return shrink()==x.shrink();
}
P &operator +=(T x){
if(this->size()==0)return *this=P{x};
(*this)[0]+=x;
return *this;
}
P &operator -=(T x){
if(this->size()==0)return *this=P{-x};
(*this)[0]+=x;
return *this;
}
P &operator *=(T x){
rep(i,0,this->size())(*this)[i]*=x;
return *this;
}
P &operator /=(T x){
return *this*=T(1)/x;
}
P &operator <<=(int x){
P ret(x,T(0));
ret.insert(ret.end(),this->begin(),this->end());
return *this=ret;
}
P &operator >>=(int x){
if((int)this->size()<=x)return *this=P();
P ret;
ret.insert(ret.end(),this->begin()+x,this->end());
return (*this)=ret;
}
P &operator +=(const P& x){
if(this->size()<x.size())this->resize(x.size(),T(0));
rep(i,0,x.size())(*this)[i]+=x[i];
return *this;
}
P &operator -=(const P& x){
if(this->size()<x.size())this->resize(x.size(),T(0));
rep(i,0,x.size())(*this)[i]-=x[i];
return *this;
}
P &operator *=(const P& x){
return *this=op(*this,x);
}
P &operator /=(P x){
if(this->size()<x.size()){this->clear();return *this;}
int n=this->size()-x.size()+1;
return *this=(rev().pre(n)*x.rev().inv(n)).pre(n).rev(n);
}
P &operator %=(const P& x){
return (*this)-=(*this)/x*x;
}
P& shrink(){while(this->size()&&this->back()==T(0))this->pop_back();return *this;}
P pre(int sz)const{
return P(this->begin(),this->begin()+min<int>(this->size(),sz));
}
P rev(int deg=-1){
P ret(*this);
if(deg!=-1)ret.resize(deg,T(0));
reverse(all(ret));
return ret;
}
P inv(int deg=-1){
assert((*this)[0]!=T(0));
const int n=deg==-1?this->size():deg;
P ret({T(1)/(*this)[0]});
for(int i=1;i<n;i<<=1){
ret*=(-ret*pre(i<<1)+2).pre(i<<1);
}
return ret.pre(n);
}
P diff(){
if((int)this->size()<=1)return P();
P ret(*this);
rep(i,0,ret.size())ret[i]*=i;
return ret>>1;
}
P integral(){
P ret(*this);
rep(i,0,ret.size())ret[i]/=i+1;
return ret<<1;
}
P log(int deg=-1){
assert((*this)[0]==T(1));
int n=deg==-1?this->size():deg;
return (diff()*inv(n)).pre(n-1).integral();
}
P exp(int deg=-1){
assert((*this)[0]==T(0));
int n=deg==-1?this->size():deg;
P ret({T(1)});
for(int i=1;i<n;i<<=1){
ret=ret*(pre(i<<1)+1-ret.log(i<<1)).pre(i<<1);
}
return ret.pre(n);
}
P pow(int c,int deg=-1){
const int n=deg==-1?this->size():deg;
long long i=0;
P ret(*static_cast<P*>(this));
while(i!=(int)this->size()&&ret[i]==0)i++;
if(i==(int)this->size())return P(n,0);
if(i*c>=n)return P(n,0);
T k=ret[i];
return ((((ret>>i)/k).log()*c).exp()*(k.pow(c))<<(i*c)).pre(n);
}
template<typename G>
P sqrt(int deg=-1,G sq=G()){
const int n=deg==-1?this->size():deg;
int tmp=0;
while((*this)[tmp]==T(0))tmp++;
if(tmp&1)return {};
if(n-tmp/2<=0)return P(n,0);
if(tmp){
return ((*this>>tmp).sqrt(n-tmp/2)<<(tmp/2)).resize(n,T(0));
}else{
P ret({T(1)});
for(int i=1;i<n;i<<=1){
ret=(ret+pre(i<<1)*ret.inv(i<<1)).pre(i<<1)/T(2);
}
return ret.pre(n);
}
}
};
struct __F__{template<typename T>T operator()(T s,T t){auto tmp=mul(s,t);return *static_cast<T*>(&tmp);}};
template<typename T>
using fps=fps_base<T,__F__>;
Back to top page