多项式四分之一家桶

因为目前半家桶里只会俩所以就成四分之一了。

多项式乘法逆

设多项式 \(A(x)\) 为 \(n\) 次多项式,求多项式 \(B\) ,使 \(A(x)*B(x)\equiv 1(\mod x^n)\) 。

设 \(A(x)*C(x)\equiv 1(\mod x^{\left\lceil\frac{n}{2}\right\rceil})\) ,那么

\[A(x)*B(x)\equiv 1(\mod x^n)\to A(x)*B(x)\equiv 1(\mod x^{\left\lceil\frac{n}{2}\right\rceil})\\ \; \\A(x)*(B(x)-C(x))\equiv 0(\mod x^{\left\lceil\frac{n}{2}\right\rceil})\\ \; \\B(x)-C(x)\equiv 0(\mod x^{\left\lceil\frac{n}{2}\right\rceil})\to (B(x)-C(x))^2\equiv 0(\mod x^n)\\ \; \\B^2(x)-2B(x)C(x)+C^2(x)\equiv 0(\mod x^n)\\ \; \\B(x)-2C(x)+A(x)C^2(x)\equiv 0(\mod x^n)\to B(x)\equiv2C(x)+A(x)C^2(x)(\mod x^n) \]

递归求解。由主定理复杂度 \(O(n\log n)\) 。

洛谷P4238[模板]多项式乘法逆
#include<bits/stdc++.h>
using namespace std;

namespace IO{
    typedef long long LL;
    int read(){
        int x=0,f=0; char ch=getchar();
        while(ch<'0'||ch>'9'){ f|=ch=='-'; ch=getchar(); }
        while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return f?-x:x;
    } char outp[50];
    void write(int x,char sp,int len=0){
        if(x<0) putchar('-'), x=-x;
        do{ outp[len++]=x%10+'0'; x/=10; }while(x);
        for(int i=len-1;~i;i--) putchar(outp[i]); putchar(sp);
    }
    void ckmin(int& x,int y){ x=x<y?x:y; }
    void ckmax(int& x,int y){ x=x>y?x:y; }
} using namespace IO;

const int NN=400010,mod=998244353;
int n;

namespace Poly_Calculation{
    const LL rt=3,two=998244355;
    int l,len,r[NN];
    LL a[NN],b[NN],g[NN],tp[NN];
    void pls(LL& x,LL y){ (x+=y)>=mod?(x-=mod):(x<0?(x+=mod):0); }
    LL qpow(LL a,int b=mod-2,LL res=1){
        for(;b;b>>=1,a=a*a%mod)
            if(b&1) res=res*a%mod;
        return res;
    }
    void prework(int n){
        for(len=1,l=0;len<=n+n;len<<=1) ++l;
        for(int i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)<<l-1);
        g[0]=1; g[1]=qpow(rt,(mod-1)/len);
        for(int i=2;i<len;i++) g[i]=g[i-1]*g[1]%mod;
    }
    void ntt(LL* a,int n){
        for(int i=0;i<n;i++) if(i<r[i]) swap(a[i],a[r[i]]);
        for(int t=n>>1,d=1;d<n;d<<=1,t>>=1)
            for(int i=0;i<n;i+=(d<<1)) for(int j=0;j<d;j++){
                LL tmp=g[j*t]*a[i+j+d]%mod;
                pls(a[i+j+d]=a[i+j],-tmp); pls(a[i+j],tmp);
            }
    }
    void polyinv(LL* a,LL* res,int deg){
        if(deg==1) return void(res[0]=qpow(a[0]));
        polyinv(a,res,deg+1>>1); prework(deg);
        for(int i=0;i<deg;i++) tp[i]=a[i];
        for(int i=deg;i<len;i++) tp[i]=0;
        ntt(res,len); ntt(tp,len);
        for(int i=0;i<len;i++) res[i]=(two-res[i]*tp[i]%mod)*res[i]%mod, g[i]=qpow(g[i]);
        ntt(res,len); LL inv=qpow(len);
        for(int i=0;i<deg;i++) res[i]=res[i]*inv%mod;
        for(int i=deg;i<len;i++) res[i]=0;
    }
} using namespace Poly_Calculation;

signed main(){
    n=read();
    for(int i=0;i<n;i++) a[i]=read();
    polyinv(a,b,n);
    for(int i=0;i<n;i++) write(b[i],' ');
    return puts(""),0;
}

多项式开根

已知 \(n\) 多项式 \(A(x)\) ,求多项式 \(B(x)\) ,满足 \(B^2(x)\equiv A(x)(\mod x^n)\) 。

类似地,设 \(C^2(x)\equiv A(x)(\mod x^{\left\lceil\frac{n}{2}\right\rceil})\) ,那么

\[B(x)\equiv C(x)(\mod x^{\left\lceil\frac{n}{2}\right\rceil})\\ \; \\B(x)-C(x)\equiv 0(\mod x^{\left\lceil\frac{n}{2}\right\rceil})\to (B(x)-C(x))^2\equiv 0(\mod x^n)\\ \; \\B^2(x)-2B(x)C(x)+C^2(x)\equiv 0(\mod x^n)\\ \; \\A(x)-2B(x)C(x)+C^2(x)\equiv 0(\mod 0)\\ \; \\B(x)=\equiv\frac{C(x)+\frac{A(x)}{C(x)}}{2}(\mod x^n) \]

递归并求逆求解。

这份板子因为某种神秘力量常数过丑了。有时间的话应该会来改改吧。(

洛谷P5205[模板]多项式开根
#include<bits/stdc++.h>
using namespace std;

namespace IO{
    typedef long long LL;
    int read(){
        int x=0,f=0; char ch=getchar();
        while(ch<'0'||ch>'9'){ f|=ch=='-'; ch=getchar(); }
        while(ch>='0'&&ch<='9'){ x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return f?-x:x;
    } char outp[50];
    void write(int x,char sp,int len=0){
        if(x<0) putchar('-'), x=-x;
        do{ outp[len++]=x%10+'0'; x/=10; }while(x);
        for(int i=len-1;~i;i--) putchar(outp[i]); putchar(sp);
    }
    void ckmin(int& x,int y){ x=x<y?x:y; }
    void ckmax(int& x,int y){ x=x>y?x:y; }
} using namespace IO;

const int NN=400010,mod=998244353;
int n;

namespace Poly_Calculation{
    const LL rt=3,two=998244355,inv2=499122177;
    int l,len,r[NN];
    LL a[NN],b[NN],g[NN],iv[NN],tp[NN];
    void pls(LL& x,LL y){ (x+=y)>=mod?(x-=mod):(x<0?(x+=mod):0); }
    LL qpow(LL a,int b=mod-2,LL res=1){
        for(;b;b>>=1,a=a*a%mod)
            if(b&1) res=res*a%mod;
        return res;
    }
    void prework(int n){
        for(len=1,l=0;len<=n+n;len<<=1) ++l;
        for(int i=0;i<len;i++) r[i]=(r[i>>1]>>1)|((i&1)<<l-1);
        g[0]=1; g[1]=qpow(rt,(mod-1)/len);
        for(int i=2;i<len;i++) g[i]=g[i-1]*g[1]%mod;
    }
    void ntt(LL* a,int n){
        for(int i=0;i<n;i++) if(i<r[i]) swap(a[i],a[r[i]]);
        for(int t=n>>1,d=1;d<n;d<<=1,t>>=1)
            for(int i=0;i<n;i+=(d<<1)) for(int j=0;j<d;j++){
                LL tmp=g[j*t]*a[i+j+d]%mod;
                pls(a[i+j+d]=a[i+j],-tmp); pls(a[i+j],tmp);
            }
    }
    void polyinv(LL* a,LL* res,int deg){
        if(deg==1) return void(res[0]=qpow(a[0]));
        polyinv(a,res,deg+1>>1); prework(deg);
        for(int i=0;i<deg;i++) tp[i]=a[i];
        ntt(res,len); ntt(tp,len);
        for(int i=0;i<len;i++) res[i]=(two-res[i]*tp[i]%mod)*res[i]%mod, g[i]=qpow(g[i]);
        ntt(res,len); LL inv=qpow(len);
        for(int i=0;i<deg;i++) res[i]=res[i]*inv%mod, tp[i]=0;;
        for(int i=deg;i<len;i++) res[i]=tp[i]=0;
    }
    void polysqr(LL* a,LL* res,int deg){
        if(deg==1) return void(res[0]=1);
        polysqr(a,res,deg+1>>1);
        polyinv(res,iv,deg); prework(deg);
        for(int i=0;i<deg;i++) tp[i]=a[i];
        ntt(res,len); ntt(iv,len); ntt(tp,len);
        for(int i=0;i<len;i++) res[i]=(tp[i]*iv[i]%mod+res[i])*inv2%mod, g[i]=qpow(g[i]);
        ntt(res,len); LL inv=qpow(len);
        for(int i=0;i<deg;i++) res[i]=res[i]*inv%mod, iv[i]=tp[i]=0;
        for(int i=deg;i<len;i++) res[i]=iv[i]=tp[i]=0;
    }
} using namespace Poly_Calculation;

signed main(){
    n=read();
    for(int i=0;i<n;i++) a[i]=read();
    polysqr(a,b,n);
    for(int i=0;i<n;i++) write(b[i],' ');
    return puts(""),0;
}
上一篇:Photoshop那些你所不知道的冷知识汇总


下一篇:PS合成非常梦幻的蒙太奇幻想世界