多项式细节梳理&模板(多项式)

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));
}

以上是关于多项式细节梳理&模板(多项式)的主要内容,如果未能解决你的问题,请参考以下文章

多项式模板

FFT/NTT及多项式运算模板

[模板] 多项式: 乘法/求逆/分治fft/微积分/ln/exp/幂

多项式模板整理

多项式相关算法模板

模板多项式开方