Kyopro Library
 
読み取り中…
検索中…
一致する文字列を見つけられません
fps.hpp
[詳解]
1#pragma once
2#include"../../kyopro_library/template.hpp"
3
4
5#include<atcoder/convolution>
6#include<atcoder/modint>
7
8/// @brief 形式的冪級数
9/// @ref borrowed from:https://potato167.github.io/po167_library
10namespace FPS {
11 /// @brief 多項式 f, g の積を返す
12 template<typename T>
13 vector<T> Mul(const vector<T>& a,const vector<T>& b) {
14 return atcoder::convolution(a,b);
15 }
16
17 /// @brief 多項式 f, g の和を返す
18 template<typename T>
19 vector<T> Add(const vector<T>& a, const vector<T>& b) {
20 vector<T> res(max(a.size(),b.size()));
21 for(int i=0; i<res.size(); i++) {
22 if(i<a.size()) res[i]+=a[i];
23 if(i<b.size()) res[i]+=b[i];
24 }
25 return res;
26 }
27
28 /// @brief 多項式 f, g の差を返す
29 template<typename T>
30 vector<T> Sub(const vector<T>& a, const vector<T>& b) {
31 vector<T> res(max(a.size(),b.size()));
32 for(int i=0; i<res.size(); i++) {
33 if(i<a.size()) res[i]+=a[i];
34 if(i<b.size()) res[i]-=b[i];
35 }
36 return res;
37 }
38
39 /// @brief 多項式 f に対し、f*g = 1 なる g を返す
40 template<typename T>
41 vector<T> Inv(vector<T> f, int len=-1) {
42 if(len==-1) len=f.size();
43 assert(f[0]!=0);
44 vector<T> g={1/f[0]};
45 int s=1;
46 while(s<len) {
47 //g=2g_s-f(g_s)^2(mod x^(2*s))
48 //g=g-(fg-1)g
49 //(fg-1)=0(mod x^(s))
50 vector<T> n_g(s*2,0),f_s(s*2,0);
51 g.resize(s*2);
52 for(int i=0; i<s*2; i++) {
53 if(int(f.size())>i) f_s[i]=f[i];
54 n_g[i]=g[i];
55 }
56 atcoder::internal::butterfly(g);
57 atcoder::internal::butterfly(f_s);
58 for(int i=0; i<s*2; i++) f_s[i]*=g[i];
59 atcoder::internal::butterfly_inv(f_s);
60 T iz=1/(T)(s*2);
61 for(int i=s; i<s*2; i++) f_s[i]*=iz;
62 for(int i=0; i<s; i++) f_s[i]=0;
63 atcoder::internal::butterfly(f_s);
64 for(int i=0; i<s*2; i++) f_s[i]*=g[i];
65 atcoder::internal::butterfly_inv(f_s);
66 for(int i=s; i<s*2; i++) n_g[i]-=f_s[i]*iz;
67 swap(n_g,g);
68 s*=2;
69 }
70 g.resize(len);
71 return g;
72 }
73
74 template<typename T>
75 vector<T> CyclicConvolution(vector<T> f, vector<T> g) {
76 atcoder::internal::butterfly(f);
77 atcoder::internal::butterfly(g);
78 for(int i=0; i<(int)f.size(); i++) f[i]*=g[i];
79 atcoder::internal::butterfly_inv(f);
80 T iz=(T)(1)/(T)(f.size());
81 for(int i=0; i<(int)f.size(); i++) f[i]*=iz;
82 return f;
83 }
84
85 /// @brief 多項式 f の積分を返す
86 template<typename T>
87 vector<T> Integral(vector<T> f) {
88 if(f.empty()) return f;
89 vector<T> num_inv((int)f.size()+1);
90 num_inv[0]=1; num_inv[1]=1;
91 auto m=T::mod();
92 for(int i=2; i<=(int)f.size(); i++) num_inv[i]=(0-num_inv[m%i])*(T)(m/i);
93 f.reserve((int)f.size()+1);
94 f.push_back(0);
95 for(int i=(int)f.size()-1; i>0; i--) f[i]=f[i-1]*num_inv[i];
96 f[0]=0;
97 return f;
98 }
99
100 /// @brief 多項式 f の微分を返す
101 template<typename T>
102 vector<T> Differential(vector<T> f) {
103 if(f.empty()) return f;
104 for(int i=0; i<(int)f.size()-1; i++) f[i]=f[i+1]*(T)(i+1);
105 f.pop_back();
106 return f;
107 }
108
109 /// @brief 多項式 f について、e^f を返す
110 template<typename T>
111 vector<T> Exp(vector<T> f, int len=-1) {
112 if(len==-1) len=f.size();
113 if(len==0) return{};
114 if(len==1) return{T(1)};
115 assert(!f.empty()&&f[0]==0);
116 int s=1;
117 //simple
118 vector<T> g={T(1)};
119 while(s<len) {
120 //g'/g
121 //A*B
122 vector<T> A=g,B=g;
123 A=Differential(A);
124 B=Inv(B,2*s);
125 A.resize(2*s);
126 A=CyclicConvolution(A,B);
127 A.pop_back();
128 A=Integral(A);
129 for(int i=0; i<s; i++) A[i]=0;
130 for(int i=s; i<s*2; i++) A[i]=(i<(int)f.size()?f[i]:0)-A[i];
131 //g_hat=g(1-g+f)
132 //g+=B=g*A
133 g.resize(2*s);
134 B=CyclicConvolution(A,g);
135 for(int i=s; i<s*2; i++) g[i]=B[i];
136 s*=2;
137 }
138 g.resize(len);
139 return g;
140 }
141
142 /// @brief 多項式 f について、log(f) を返す
143 template<typename T>
144 vector<T> Log(vector<T> f, int len=-1) {
145 if(len==-1) len=f.size();
146 if(len==0) return{};
147 if(len==1) return{T(0)};
148 assert(!f.empty()&&f[0]==1);
149 vector<T> res=atcoder::convolution(Differential(f),Inv(f,len));
150 res.resize(len-1);
151 return Integral(res);
152 }
153
154 /// @brief 多項式 f^M を返す
155 template<class T>
156 vector<T> Pow(vector<T> f, ll M, int len=-1) {
157 if(len==-1) len=f.size();
158 vector<T> res(len,0);
159 if(M==0) {
160 res[0]=1;
161 return res;
162 }
163 for(int i=0; i<(int)f.size(); i++) {
164 if(f[i]==0) continue;
165 if(i>(len-1)/M) break;
166 vector<T> g((int)f.size()-i);
167 T v=(T)(1)/(T)(f[i]);
168 for(int j=i; j<(int)f.size(); j++) g[j-i]=f[j]*v;
169 ll zero=i*M;
170 if(i) len-=i*M;
171 g=Log(g,len);
172 for(T& x:g) x*=M;
173 g=Exp(g,len);
174 v=(T)(1)/v;
175 T c=1;
176 while(M) {
177 if(M&1) c=c*v;
178 v=v*v;
179 M>>=1;
180 }
181 for(int i=0; i<len; i++) res[i+zero]=g[i]*c;
182 return res;
183 }
184 return res;
185 }
186
187 //in :DFT(v)(len(v)=z)
188 //out:DFT(v)(len(v)=2*z)
189 template<typename T>
190 void Extend(vector<T>& v) {
191 int z=v.size();
192 T e=(T(atcoder::internal::primitive_root_constexpr(T::mod()))).pow(T::mod()/(2*z));
193 auto cp=v;
194 atcoder::internal::butterfly_inv(cp);
195 T tmp=(T)(1)/(T)(z);
196 for(int i=0; i<z; i++) {
197 cp[i]*=tmp;
198 tmp*=e;
199 }
200 atcoder::internal::butterfly(cp);
201 for(int i=0; i<z; i++) v.push_back(cp[i]);
202 }
203
204 //s.t|v|=2^s(no assert)
205 template<typename T>
206 void PickEvenOdd(vector<T>& v, int odd) {
207 int z=v.size()/2;
208 T half=(T)(1)/(T)(2);
209 if(odd==0) {
210 for(int i=0; i<z; i++) v[i]=(v[i*2]+v[i*2+1])*half;
211 v.resize(z);
212 }else{
213 T e=(T(atcoder::internal::primitive_root_constexpr(T::mod()))).pow(T::mod()/(2*z));
214 T ie=T(1)/e;
215 vector<T> es={half};
216 while((int)es.size()!=z) {
217 vector<T> n_es((int)es.size()*2);
218 for(int i=0; i<(int)es.size(); i++) {
219 n_es[i*2]=(es[i]);
220 n_es[i*2+1]=(es[i]*ie);
221 }
222 ie*=ie;
223 swap(n_es,es);
224 }
225 for(int i=0; i<z; i++) v[i]=(v[i*2]-v[i*2+1])*es[i];
226 v.resize(z);
227 }
228 }
229
230 /// @brief 多項式 f, g について、`f = gq + r` なる q, r を返す
231 template<typename T>
233 int n=f.size(),m=g.size();
234 if(n<m) return{{},f};
235 vector<T> r=f;
236 reverse(ALL(f)); reverse(ALL(g));
237 f.resize(n-m+1);
238 vector<T> q=Mul(f,Inv(g,n-m+1));
239 q.resize(n-m+1);
240 reverse(ALL(q)); reverse(ALL(g));
241 r=Sub(r,Mul(q,g));
242 while(!q.empty()&&q.back()==0) q.pop_back();
243 while(!r.empty()&&r.back()==0) r.pop_back();
244 return {q,r};
245 }
246
247 /// @brief `[x^k](P/Q)` を返す
248 template<typename T>
249 T BostonMori(ll k, vector<T> P, vector<T> Q) {
250 assert(!Q.empty()&&Q[0]!=0);
251 int z=1;
252 while(z<(int)max(P.size(),Q.size())) z*=2;
253 P.resize(z*2,0); Q.resize(z*2,0);
254 atcoder::internal::butterfly(P); atcoder::internal::butterfly(Q);
255 //fast
256 while(k) {
257 //Q(-x)
258 vector<T> Q_n(z*2);
259 for(int i=0; i<z; i++) {
260 Q_n[i*2]=Q[i*2+1];
261 Q_n[i*2+1]=Q[i*2];
262 }
263 for(int i=0; i<z*2; i++) {
264 P[i]*=Q_n[i];
265 Q[i]*=Q_n[i];
266 }
267 PickEvenOdd(P,k&1);
268 PickEvenOdd(Q,0);
269 k/=2;
270 if(k==0) break;
271 Extend(P);
272 Extend(Q);
273 }
274 T SP=0,SQ=0;
275 for(int i=0; i<z; i++) SP+=P[i],SQ+=Q[i];
276 return SP/SQ;
277 }
278
279 //0=a[i]*c[0]+a[i-1]*c[1]+a[i-2]*c[2]+...+a[i-d]*c[d]
280 //a.size()+1==c.size()
281 //c[0]=-1?
282 //return a[k]
283 template<typename T>
284 T KthLinear(ll k, vector<T> a, vector<T> c) {
285 int d=a.size();
286 assert(d+1==int(c.size()));
287 vector<T> P=atcoder::convolution(a,c);
288 P.resize(d);
289 return BostanMori(k,P,c);
290 }
291}
形式的冪級数 borrowed from:https://potato167.github.io/po167_library
Definition fps.hpp:10
vector< T > Log(vector< T > f, int len=-1)
多項式 f について、log(f) を返す
Definition fps.hpp:144
vector< T > Differential(vector< T > f)
多項式 f の微分を返す
Definition fps.hpp:102
void Extend(vector< T > &v)
Definition fps.hpp:190
vector< T > CyclicConvolution(vector< T > f, vector< T > g)
Definition fps.hpp:75
vector< T > Sub(const vector< T > &a, const vector< T > &b)
多項式 f, g の差を返す
Definition fps.hpp:30
vector< T > Exp(vector< T > f, int len=-1)
多項式 f について、e^f を返す
Definition fps.hpp:111
vector< T > Inv(vector< T > f, int len=-1)
多項式 f に対し、f*g = 1 なる g を返す
Definition fps.hpp:41
void PickEvenOdd(vector< T > &v, int odd)
Definition fps.hpp:206
vector< T > Integral(vector< T > f)
多項式 f の積分を返す
Definition fps.hpp:87
vector< T > Mul(const vector< T > &a, const vector< T > &b)
多項式 f, g の積を返す
Definition fps.hpp:13
vector< T > Add(const vector< T > &a, const vector< T > &b)
多項式 f, g の和を返す
Definition fps.hpp:19
T BostonMori(ll k, vector< T > P, vector< T > Q)
[x^k](P/Q) を返す
Definition fps.hpp:249
T KthLinear(ll k, vector< T > a, vector< T > c)
Definition fps.hpp:284
vector< T > Pow(vector< T > f, ll M, int len=-1)
多項式 f^M を返す
Definition fps.hpp:156
#define ALL(x)
Definition template.hpp:4