多项式细节梳理&模板(多项式)
Posted flashhu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了多项式细节梳理&模板(多项式)相关的知识,希望对你有一定的参考价值。
基础
现在的码风又变了。。。
FFT和NTT的板子
typedef complex<double> C;
const double PI=acos(-1);
void FFT(C*a,R op){
for(R i=0;i<N;++i)
if(i<r[i])swap(a[i],a[r[i]]);
for(R i=1;i<N;i<<=1){
C wn=C(cos(PI/i),sin(PI/i)*op),w=1,t;
for(R j=0;j<N;j+=i<<1,w=1)
for(R k=j;k<j+i;++k,w*=wn)
t=a[k+i]*w,a[k+i]=a[k]-t,a[k]+=t;
}
}
const int YL=998244353;
LL qpow(LL b,R k){
LL a=1;
for(;k;k>>=1,b=b*b%YL)
if(k&1)a=a*b%YL;
return a;
}
void NTT(R*a,R n,R op){
for(R i=0;i<n;++i)
if(i<r[i])swap(a[i],a[r[i]]);
for(R i=1;i<n;i<<=1){
LL wn=qpow(3,(YL-1)/(i<<1));
if(op==-1)wn=qpow(wn,YL-2);
for(R j=0;j<n;j+=i<<1)
for(R k=j,w=1,x,y;k<j+i;++k,w=w*wn%YL)
x=a[k],y=(LL)a[k+i]*w%YL,a[k]=Mod(x+y),a[k+i]=Mod(x-y+YL);
}
if(op==1)return;
R in=qpow(n,YL-2);
for(R i=0;i<n;++i)a[i]=(LL)a[i]*in%YL;
}
多项式运算
牛顿迭代
已知多项式函数(F(x)),用倍增法求解(B)使得(F(B)equiv0(mod x^{2^k}))。
(B_1=B-frac{F(B)}{F'(B)})
接下来的(A)为已知多项式,B为待求多项式。
求逆
(F(B)=AB-1=0)
(B_1=B-frac{AB-1}{A}=B-B(AB-1)=2B-AB^2)
开方
(F(B)=B^2-A=0)
(B_1=B-frac{B^2-A}{2B}=frac{B^2+A}{2B})
对数
没必要迭代。
(B=ln A)
(B=intfrac{A'}{A})
指数
(B=e^A)
(ln B-A=0)
(B_1=B-frac{ln B-A}{frac1B}=B(1+A-ln B))
代码模板
写的时候保证了一定的稳定性(数组清空问题),因此牺牲了一丁点效率。
参数中,a为已知,b为待求,a1、b1为辅助数组。
传入前需自己确保b、a1、b1是否为空。
返回后保证a维持原状,b存好答案,a1、b1为空。
还有开方,除法,拉格朗日反演待填坑
const int YL=998244353;
int Inv[N],r[N];//在外面初始化逆元
inline int Mod(const int x){
return x>=YL?x-YL:x;
}
LL qpow(LL b,R k){
LL a=1;
for(;k;k>>=1,b=b*b%YL)
if(k&1)a=a*b%YL;
return a;
}
int Init(R m){
R n=1;while(n<m<<1)n<<=1;
for(R i=0;i<n;++i)r[i]=(r[i>>1]|(1&i)*n)>>1;
return n;
}
void NTT(R*a,R n,R op){
for(R i=0;i<n;++i)
if(i<r[i])swap(a[i],a[r[i]]);
for(R i=1;i<n;i<<=1){
LL wn=qpow(3,(YL-1)/(i<<1));
if(op==-1)wn=qpow(wn,YL-2);
for(R j=0;j<n;j+=i<<1)
for(R k=j,w=1,x,y;k<j+i;++k,w=w*wn%YL)
x=a[k],y=(LL)a[k+i]*w%YL,a[k]=Mod(x+y),a[k+i]=Mod(x-y+YL);
}
if(op==1)return;
R in=qpow(n,YL-2);
for(R i=0;i<n;++i)a[i]=(LL)a[i]*in%YL;
}
void PolyDer(R*a,R*b,R n){
for(R i=1;i<n;++i)b[i-1]=(LL)a[i]*i%YL;
if(a==b)a[n-1]=0;
}
void PolyInt(R*a,R*b,R n){
for(R i=n;i;--i)b[i]=(LL)a[i-1]*Inv[i]%YL;
if(a==b)a[0]=0;
}
void PolyInv(R*a,R*b,R*a1,R m){
if(m==1){b[0]=qpow(a[0],YL-2);return;}
PolyInv(a,b,a1,(m+1)>>1);memcpy(a1,a,4*m);
R n=Init(m);NTT(b,n,1);NTT(a1,n,1);
for(R i=0;i<n;++i)b[i]=(YL+2-(LL)b[i]*a1[i]%YL)*b[i]%YL;
NTT(b,n,-1);memset(a1,0,4*n);memset(b+m,0,4*(n-m));
}
void PolyLn(R*a,R*b,R*a1,R m){
PolyInv(a,b,a1,m);PolyDer(a,a1,m);
R n=Init(m);NTT(b,n,1);NTT(a1,n,1);
for(R i=0;i<n;++i)b[i]=(LL)b[i]*a1[i]%YL;
NTT(b,n,-1);memset(a1,0,4*n);PolyInt(b,b,m);
}
void PolyExp(R*a,R*b,R*a1,R*b1,R m){
if(m==1){b[0]=1;return;}
PolyExp(a,b,a1,b1,(m+1)>>1);PolyLn(b,b1,a1,m);memcpy(a1,a,4*m);
R n=Init(m);NTT(b,n,1);NTT(a1,n,1);NTT(b1,n,1);
for(R i=0;i<n;++i)b[i]=(LL)b[i]*(YL+1+a1[i]-b1[i])%YL;
NTT(b,n,-1);memset(a1,0,4*n);memset(b1,0,4*n);memset(b+m,0,4*(n-m));
}
以上是关于多项式细节梳理&模板(多项式)的主要内容,如果未能解决你的问题,请参考以下文章