码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-12-19 22:00:16      阅读:161      评论:0      收藏:0      [点我收藏+]

标签:模板   www.   多项式运算   return   amp   for   数组   code   htm   

基础

很久以前的多项式总结

现在的码风又变了。。。

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=\int\frac{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));
}

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

标签:模板   www.   多项式运算   return   amp   for   数组   code   htm   

原文地址:https://www.cnblogs.com/flashhu/p/10146087.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!