1+ #pragma once
2+ #include " polynomial/ntt.hpp"
3+
4+ /* *
5+ * Author: Teetat T.
6+ * Date: 2024-03-17
7+ * Description: basic operations of formal power series
8+ */
9+
10+ template <class mint >
11+ struct FormalPowerSeries :vector<mint>{
12+ using vector<mint>::vector;
13+ using FPS = FormalPowerSeries;
14+
15+ FPS &operator +=(const FPS &rhs){
16+ if (rhs.size ()>this ->size ())this ->resize (rhs.size ());
17+ for (int i=0 ;i<rhs.size ();i++)(*this )[i]+=rhs[i];
18+ return *this ;
19+ }
20+ FPS &operator +=(const mint &rhs){
21+ if (this ->empty ())this ->resize (1 );
22+ (*this )[0 ]+=rhs;
23+ return *this ;
24+ }
25+ FPS &operator -=(const FPS &rhs){
26+ if (rhs.size ()>this ->size ())this ->resize (rhs.size ());
27+ for (int i=0 ;i<rhs.size ();i++)(*this )[i]-=rhs[i];
28+ return *this ;
29+ }
30+ FPS &operator -=(const mint &rhs){
31+ if (this ->empty ())this ->resize (1 );
32+ (*this )[0 ]-=rhs;
33+ return *this ;
34+ }
35+ FPS &operator *=(const FPS &rhs){
36+ auto res=NTT<mint>()(*this ,rhs);
37+ return *this =FPS (res.begin (),res.end ());
38+ }
39+ FPS &operator *=(const mint &rhs){
40+ for (auto &a:*this )a*=rhs;
41+ return *this ;
42+ }
43+ friend FPS operator +(FPS lhs,const FPS &rhs){return lhs+=rhs;}
44+ friend FPS operator +(FPS lhs,const mint &rhs){return lhs+=rhs;}
45+ friend FPS operator +(const mint &lhs,FPS &rhs){return rhs+=lhs;}
46+ friend FPS operator -(FPS lhs,const FPS &rhs){return lhs-=rhs;}
47+ friend FPS operator -(FPS lhs,const mint &rhs){return lhs-=rhs;}
48+ friend FPS operator -(const mint &lhs,FPS rhs){return -(rhs-lhs);}
49+ friend FPS operator *(FPS lhs,const FPS &rhs){return lhs*=rhs;}
50+ friend FPS operator *(FPS lhs,const mint &rhs){return lhs*=rhs;}
51+ friend FPS operator *(const mint &lhs,FPS rhs){return rhs*=lhs;}
52+
53+ FPS operator -(){return (*this )*-1 ;}
54+
55+ FPS rev (){
56+ FPS res (*this );
57+ reverse (res.beign (),res.end ());
58+ return res;
59+ }
60+ FPS pre (int sz){
61+ FPS res (this ->begin (),this ->begin ()+min ((int )this ->size (),sz));
62+ if (res.size ()<sz)res.resize (sz);
63+ return res;
64+ }
65+ FPS shrink (){
66+ FPS res (*this );
67+ while (!res.empty ()&&res.back ()==mint{})res.pop_back ();
68+ return res;
69+ }
70+ FPS operator >>(int sz){
71+ if (this ->size ()<=sz)return {};
72+ FPS res (*this );
73+ res.erase (res.begin (),res.begin ()+sz);
74+ return res;
75+ }
76+ FPS operator <<(int sz){
77+ FPS res (*this );
78+ res.insert (res.begin (),sz,mint{});
79+ return res;
80+ }
81+ FPS diff (){
82+ const int n=this ->size ();
83+ FPS res (max (0 ,n-1 ));
84+ for (int i=1 ;i<n;i++)res[i-1 ]=(*this )[i]*mint (i);
85+ return res;
86+ }
87+ FPS integral (){
88+ const int n=this ->size ();
89+ FPS res (n+1 );
90+ res[0 ]=0 ;
91+ if (n>0 )res[1 ]=1 ;
92+ ll mod=mint::get_mod ();
93+ for (int i=2 ;i<=n;i++)res[i]=(-res[mod%i])*(mod/i);
94+ for (int i=0 ;i<n;i++)res[i+1 ]*=(*this )[i];
95+ return res;
96+ }
97+ mint eval (const mint &x){
98+ mint res=0 ,w=1 ;
99+ for (auto &a:*this )res+=a*w,w*=x;
100+ return res;
101+ }
102+
103+ FPS inv (int deg=-1 ){
104+ assert (!this ->empty ()&&(*this )[0 ]!=mint (0 ));
105+ if (deg==-1 )deg=this ->size ();
106+ FPS res{mint (1 )/(*this )[0 ]};
107+ for (int i=2 ;i>>1 <deg;i<<=1 ){
108+ res=(res*(mint (2 )-res*pre (i))).pre (i);
109+ }
110+ return res.pre (deg);
111+ }
112+ FPS log (int deg=-1 ){
113+ assert (!this ->empty ()&&(*this )[0 ]==mint (1 ));
114+ if (deg==-1 )deg=this ->size ();
115+ return (pre (deg).diff ()*inv (deg)).pre (deg-1 ).integral ();
116+ }
117+ FPS exp (int deg=-1 ){
118+ assert (this ->empty ()||(*this )[0 ]==mint (0 ));
119+ if (deg==-1 )deg=this ->size ();
120+ FPS res{mint (1 )};
121+ for (int i=2 ;i>>1 <deg;i<<=1 ){
122+ res=(res*(pre (i)-res.log (i)+mint (1 ))).pre (i);
123+ }
124+ return res.pre (deg);
125+ }
126+ FPS pow (ll k,int deg=-1 ){
127+ const int n=this ->size ();
128+ if (deg==-1 )deg=n;
129+ if (k==0 ){
130+ FPS res (deg);
131+ if (deg)res[0 ]=mint (1 );
132+ return res;
133+ }
134+ for (int i=0 ;i<n;i++){
135+ if (__int128_t (i)*k>=deg)return FPS (deg,mint (0 ));
136+ if ((*this )[i]==mint (0 ))continue ;
137+ mint rev=mint (1 )/(*this )[i];
138+ FPS res=(((*this *rev)>>i).log (deg)*k).exp (deg);
139+ res=((res*binpow ((*this )[i],k))<<(i*k)).pre (deg);
140+ return res;
141+ }
142+ return FPS (deg,mint (0 ));
143+ }
144+ };
0 commit comments