多项式小结
A1443356159 · · 个人记录
多项式小结
会过 。 ---XXX
多项式乘法
NTT,FFT,不多说了。
多项式求逆
考虑递归求解。
现求
则,
最后一步是两边同时乘上
void Finv(int n,LL *F,LL *G) {//G=F^(-1)
if(n==1){G[0]=qpow(F[0],P-2);return;}
Finv((n+1)>>1,F,G);//注意是向上取整
int len=0;while((1<<len)<(n<<1))++len;
for(int i=0;i<n;++i)C[i]=F[i];
for(int i=n;i<(1<<len);++i)C[i]=0;//一定要清空
NTT(C,len,1);NTT(G,len,1);
for(int i=0;i<(1<<len);++i)G[i]=(2-C[i]*G[i]%P+P)%P*G[i]%P;
NTT(G,len,-1);
for(int i=n;i<(1<<len);++i)G[i]=0;//一定要清空
}
多项式开根
依旧是考虑递归求解。
现求
最后一步是因为
多项式开根要求常数项一定要是1。
void Fsqrt(int n,LL *F,LL *G) {
if(n==1){G[0]=1;return;}
Fsqrt((n+1)>>1,F,G);
int len=0;while((1<<len)<(n<<1))++len;
for(int i=0;i<n;++i)C[i]=F[i];
for(int i=n;i<(1<<len);++i)C[i]=0;
for(int i=0;i<(1<<len);++i)Ni[i]=D[i]=0;//注意清空
Finv(n,G,Ni);
NTT(C,len,1);NTT(G,len,1);NTT(Ni,len,1);
for(int i=0;i<(1<<len);++i)
G[i]=(C[i]+G[i]*G[i]%P)*Ni[i]%P*inv2%P;
NTT(G,len,-1);
for(int i=n;i<(1<<len);++i)G[i]=0;
}
多项式 \ln
求
首先要会一点求导。
具体实现就是求导算
关于多项式求导,其实是逐项求导再加起来。
若
若
多项式
void Fln(int n,LL *F,LL *G){
Finv(n,F,Ni);
for(int i=0;i<n-1;++i)DF[i]=F[i+1]*(i+1)%P;
int len=0;while((1<<len)<(n<<1))++len;
NTT(Ni,len,1);NTT(DF,len,1);
for(int i=0;i<(1<<len);++i)G[i]=DF[i]*Ni[i]%P;
NTT(G,len,-1);
for(int i=n-1;i>0;--i)G[i]=G[i-1]*qpow(i,P-2)%P;
G[0]=0;
}
多项式 \exp
这个最复杂了,既要求逆,求
现求
令
若已知
将后面的式子泰勒展开,
其中
注意到
原因大概是
所以有,
于是,
把
void Fexp(int n,LL *F,LL *G) {
if(n==1){G[0]=1;return;}
Fexp((n+1)>>1,F,G);
int len=0;while((1<<len)<(n<<1))++len;
Fln(n,G,Ln);
for(int i=0;i<n;++i)D[i]=F[i];
for(int i=n;i<(1<<len);++i)D[i]=0;
NTT(D,len,1);NTT(Ln,len,1);NTT(G,len,1);
for(int i=0;i<(1<<len);++i)G[i]=G[i]*(1-Ln[i]+D[i]+P)%P;
NTT(G,len,-1);
for(int i=n;i<(1<<len);++i)G[i]=0;
}