• 多项式全家桶


    FFThttps://www.lydsy.com/JudgeOnline/problem.php?id=2179

    #include<bits/stdc++.h>
    #define pi acos(-1)
    using namespace std;
    typedef complex<double>cp;
    int n,m,L,R[131078],ans[131078];
    cp a[131078],b[131078];
    char s[131078];
    void fft(cp *a,int f)
    {
        for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]);
        for(int i=1;i<n;i<<=1)
        {
            cp wn(cos(pi/i),f*sin(pi/i));
            for(int p=i*2,j=0;j<n;j+=p)
            {
                cp w(1,0);
                for(int k=0;k<i;k++,w*=wn)
                {
                    cp x=a[j+k],y=w*a[j+k+i];
                    a[j+k]=x+y;a[j+k+i]=x-y;
                }
            }
        }
    }
    int main()
    {
        scanf("%d",&n);
        scanf("%s",s);
        for(int i=0;i<n;i++)a[n-i-1]=s[i]-'0';
        scanf("%s",s);
        for(int i=0;i<n;i++)b[n-i-1]=s[i]-'0';
        n--;m=n*2;
        for(n=1;n<=m;n*=2)L++;
        for(int i=0;i<n;i++)R[i]=(R[i/2]/2)|((i&1)<<L-1);
        fft(a,1);fft(b,1);
        for(int i=0;i<=n;i++)a[i]=a[i]*b[i];
        fft(a,-1);
        int x=0;
        for(int i=0;i<=m;i++)
        ans[i]=(int)(a[i].real()/n+0.5);
        for(int i=0;i<=m;i++)
        ans[i+1]+=ans[i]/10,ans[i]%=10;
        if(ans[m+1])m++;
        for(int i=m;i>=0;i--)printf("%d",ans[i]);
    }

    NTT与FFT类似就没了

    分治NTThttps://www.luogu.org/problemnew/show/P4721

    #include<bits/stdc++.h>
    using namespace std;
    const int N=53e4,mod=998244353;
    int n,a[N],A[N],B[N],f[N],R[N];
    int qpow(int a,int b)
    {
        int ret=1;
        while(b)
        {
            if(b&1)ret=1ll*ret*a%mod;
            a=1ll*a*a%mod,b>>=1;
        }
        return ret;
    }
    void init(int L){for(int i=0;i<(1<<L);i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1);}
    void NTT(int*a,int n,int tp)
    {
        for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]);
        for(int i=1;i<n;i<<=1)
        {
            int wn=qpow(3,mod/(i<<1));
            if(tp==-1)wn=qpow(wn,mod-2);
            for(int j=0;j<n;j+=i<<1)
            for(int k=0,w=1;k<i;k++,w=1ll*w*wn%mod)
            {
                int x=a[j+k],y=1ll*a[i+j+k]*w%mod;
                a[j+k]=(x+y)%mod,a[i+j+k]=(x-y+mod)%mod;
            }
        }
        if(tp==1)return;
        int inv=qpow(n,mod-2);
        for(int i=0;i<n;i++)a[i]=1ll*a[i]*inv%mod;
    }
    void cdq(int l,int r)
    {
        if(l==r)return;
        int mid=l+r>>1;
        cdq(l,mid);
        int L=1,now=1,nn;
        while(now<=r-l+1)now*=2,L++;
        init(L);
        nn=1<<L;
        for(int i=0;i<=nn;i++)A[i]=B[i]=0;
        for(int i=l;i<=mid;i++)A[i-l]=f[i];
        for(int i=1;i<=r-l;i++)B[i-1]=a[i];
        NTT(A,nn,1),NTT(B,nn,1);
        for(int i=0;i<=nn;i++)A[i]=1ll*A[i]*B[i]%mod;
        NTT(A,nn,-1);
        for(int i=mid+1;i<=r;i++)f[i]=(f[i]+A[i-l-1])%mod;
        cdq(mid+1,r);
    }
    int main()
    {
        scanf("%d",&n);
        f[0]=1;
        for(int i=1;i<n;i++)scanf("%d",&a[i]);
        cdq(0,n-1);
        for(int i=0;i<n;i++)printf("%d ",f[i]);
    }

    FWThttps://www.luogu.org/problemnew/show/P4717

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=998244353,inv2=499122177,N=1<<17;
    int n,all,a[N],b[N],c[N],d[N];
    void FWT_or(int*a,int n,int f)
    {
        for(int i=1;i<n;i*=2)
        for(int j=0;j<n;j+=i*2)
        for(int k=0;k<i;k++)
        {
            int x=a[j+k],y=a[j+k+i];
            a[j+k+i]=f==1?(x+y)%mod:(y-x+mod)%mod;
        }
    }
    void FWT_and(int*a,int n,int f)
    {
        for(int i=1;i<n;i*=2)
        for(int j=0;j<n;j+=i*2)
        for(int k=0;k<i;k++)
        {
            int x=a[j+k],y=a[j+k+i];
            a[j+k]=f==1?(x+y)%mod:(x-y+mod)%mod;
        }
    }
    void FWT_xor(int*a,int n,int f)
    {
        for(int i=1;i<n;i*=2)
        for(int j=0;j<n;j+=i*2)
        for(int k=0;k<i;k++)
        {
            int x=a[j+k],y=a[j+k+i];
            a[j+k]=(x+y)%mod;a[j+k+i]=(x-y+mod)%mod;
            if(f==-1)
            {
                a[j+k]=1ll*a[j+k]*inv2%mod;
                a[j+k+i]=1ll*a[j+k+i]*inv2%mod;
            }
        }
    }
    int main()
    {
        scanf("%d",&n);all=1<<n;
        for(int i=0;i<all;i++)scanf("%d",&a[i]),c[i]=a[i];
        for(int i=0;i<all;i++)scanf("%d",&b[i]),d[i]=b[i];
        FWT_or(c,all,1);FWT_or(d,all,1);
        for(int i=0;i<all;i++)c[i]=1ll*c[i]*d[i]%mod;
        FWT_or(c,all,-1);
        for(int i=0;i<all;i++)printf("%d ",c[i]);
        puts("");
        memcpy(c,a,sizeof c);
        memcpy(d,b,sizeof d);
        FWT_and(c,all,1);FWT_and(d,all,1);
        for(int i=0;i<all;i++)c[i]=1ll*c[i]*d[i]%mod;
        FWT_and(c,all,-1);
        for(int i=0;i<all;i++)printf("%d ",c[i]);
        puts("");
        memcpy(c,a,sizeof c);
        memcpy(d,b,sizeof d);
        FWT_xor(c,all,1);FWT_xor(d,all,1);
        for(int i=0;i<all;i++)c[i]=1ll*c[i]*d[i]%mod;
        FWT_xor(c,all,-1);
        for(int i=0;i<all;i++)printf("%d ",c[i]);
    }

    任意模数NTThttps://www.luogu.org/problemnew/show/P4245

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int P1=469762049,P2=998244353,P3=1004535809,N=3e6+7;
    const ll PP=1ll*P1*P2;
    int n,m,p,len=1,L,A[N],B[N],C[N],D[N],ans[3][N],R[N];
    ll qmul(ll a,ll b,ll mod)
    {
        a%=mod;b%=mod;
        ll ret=0;
        while(b)
        {
            if(b&1)ret=(ret+a)%mod;
            a=(a+a)%mod;b>>=1;
        }
        return ret;
    }
    int qpow(int a,int b,int mod)
    {
        int ret=1;
        while(b)
        {
            if(b&1)ret=1ll*ret*a%mod;
            a=1ll*a*a%mod;b>>=1;
        }
        return ret;
    }
    void NTT(int*A,int n,int f,int mod)
    {
        for(int i=0;i<n;i++)if(i<R[i])swap(A[i],A[R[i]]);
        for(int i=1;i<n;i*=2)
        {
            int wn=qpow(f==1?3:qpow(3,mod-2,mod),(mod-1)/(i<<1),mod);
            for(int j=0;j<n;j+=i*2)
            for(int k=0,w=1;k<i;k++,w=1ll*w*wn%mod)
            {
                int x=A[j+k],y=1ll*w*A[i+j+k]%mod;
                A[j+k]=(x+y)%mod;
                A[i+j+k]=(x-y+mod)%mod;
            }
        }
        if(f==-1)
        {
            int inv=qpow(n,mod-2,mod);
            for(int i=0;i<n;i++)A[i]=1ll*A[i]*inv%mod;
        }
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&p);
        for(int i=0;i<=n;i++)scanf("%d",&A[i]);
        for(int i=0;i<=m;i++)scanf("%d",&B[i]);
        while(len<=n+m)len<<=1,L++;
        for(int i=0;i<=len;i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
        copy(A,A+n+1,C);copy(B,B+m+1,D);
        NTT(C,len,1,P1);NTT(D,len,1,P1);
        for(int i=0;i<=len;i++)ans[0][i]=1ll*C[i]*D[i]%P1;
        memset(C,0,sizeof C);memset(D,0,sizeof D);
        copy(A,A+n+1,C);copy(B,B+m+1,D);
        NTT(C,len,1,P2);NTT(D,len,1,P2);
        for(int i=0;i<=len;i++)ans[1][i]=1ll*C[i]*D[i]%P2;
        memset(C,0,sizeof C);memset(D,0,sizeof D);
        copy(A,A+n+1,C);copy(B,B+m+1,D);
        NTT(C,len,1,P3);NTT(D,len,1,P3);
        for(int i=0;i<=len;i++)ans[2][i]=1ll*C[i]*D[i]%P3;
        NTT(ans[0],len,-1,P1);
        NTT(ans[1],len,-1,P2);
        NTT(ans[2],len,-1,P3);
        for(int i=0;i<=n+m;i++)
        {
            ll A=(qmul(1ll*ans[0][i]*P2%PP,qpow(P2%P1,P1-2,P1),PP)+qmul(1ll*ans[1][i]*P1%PP,qpow(P1%P2,P2-2,P2),PP))%PP;
            ll K=((ans[2][i]-A)%P3+P3)%P3*qpow(PP%P3,P3-2,P3)%P3;
            printf("%d ",(A%p+K%p*(PP%p)%p)%p);
        }
    }

    多项式求逆https://www.luogu.org/problemnew/show/P4238

    #include<bits/stdc++.h>
    using namespace std;
    const int mod=998244353,N=4e5+7;
    int a[N],b[N],c[N],R[N];
    int qpow(int a,int b)
    {
        int ret=1;
        while(b)
        {
            if(b&1)ret=1ll*ret*a%mod;
            a=1ll*a*a%mod;b>>=1;
        }
        return ret;
    }
    void NTT(int*a,int n,int f)
    {
        for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]);
        for(int i=1;i<n;i*=2)
        {
            int wn=qpow(3,(mod-1)/(i*2));
            for(int j=0;j<n;j+=i*2)
            {
                int w=1;
                for(int k=0,x,y;k<i;k++,w=1ll*w*wn%mod)
                {
                    x=a[j+k];y=1ll*w*a[j+k+i]%mod;
                    a[j+k]=(x+y)%mod;a[j+k+i]=((x-y)%mod+mod)%mod;
                }
            }
        }
        if(f==1)return;
        int nv=qpow(n,mod-2);
        reverse(a+1,a+n);
        for(int i=0;i<n;i++)a[i]=1ll*a[i]*nv%mod;
    }
    void inv(int deg,int*a,int*b)
    {
        if(deg==1){b[0]=qpow(a[0],mod-2);return;}
        inv((deg+1)/2,a,b);
        int L=0,n=1;
        while(n<deg*2)n*=2,L++;
        for(int i=1;i<n;i++)R[i]=(R[i>>1]>>1)|((i&1)<<(L-1));
        for(int i=0;i<deg;i++)c[i]=a[i];
        for(int i=deg;i<n;i++)c[i]=0;
        NTT(c,n,1);NTT(b,n,1);
        for(int i=0;i<n;i++)b[i]=((2ll-1ll*c[i]*b[i]%mod)+mod)*b[i]%mod;
        NTT(b,n,-1);
        for(int i=deg;i<n;i++)b[i]=0;
    }
    int main()
    {
        int n;scanf("%d",&n);
        for(int i=0;i<n;i++)scanf("%d",&a[i]);
        inv(n,a,b);
        for(int i=0;i<n;i++)printf("%d ",b[i]);
    }

    多项式开根https://www.luogu.org/problemnew/show/P5205

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4e5+7,mod=998244353,inv2=499122177;
    int n,f[N],g[N],A[N],B[N],C[N],D[N],R[N];
    int qpow(int a,int b)
    {
        int ret=1;
        while(b)
        {
            if(b&1)ret=1ll*ret*a%mod;
            a=1ll*a*a%mod,b>>=1;
        }
        return ret;
    }
    void NTT(int *a,int n,int tp)
    {
        for(int i=0;i<n;i++)if(i<R[i])swap(a[i],a[R[i]]);
        for(int i=1;i<n;i<<=1)
        {
            int wn=qpow(3,mod/(i<<1));
            if(tp==-1)wn=qpow(wn,mod-2);
            for(int j=0;j<n;j+=i<<1)
            for(int k=0,w=1;k<i;k++,w=1ll*w*wn%mod)
            {
                int x=a[j+k],y=1ll*a[i+j+k]*w%mod;
                a[j+k]=(x+y)%mod,a[i+j+k]=(x-y+mod)%mod;
            }
        }
        if(tp==1)return;
        int invn=qpow(n,mod-2);
        for(int i=0;i<n;i++)a[i]=1ll*a[i]*invn%mod;
    }
    void inv(int*a,int*b,int n)
    {
        b[0]=qpow(a[0],mod-2);
        int len,lim;
        for(len=1;len<(n<<1);len<<=1)
        {
            lim=len<<1;
            for(int i=0;i<len;i++)A[i]=a[i],B[i]=b[i];
            for(int i=0;i<lim;i++)R[i]=(R[i>>1]>>1)|((i&1)?len:0);
            NTT(A,lim,1),NTT(B,lim,1);
            for(int i=0;i<lim;i++)b[i]=(2-1ll*A[i]*B[i]%mod+mod)*B[i]%mod;
            NTT(b,lim,-1);
            for(int i=len;i<lim;i++)b[i]=0;
        }
        for(int i=0;i<len;i++)A[i]=B[i]=0;
        for(int i=n;i<len;i++)b[i]=0;
    }
    void Sqrt(int*a,int*b,int n)
    {
        b[0]=1;
        int *A=C,*B=D,len,lim;
        for(len=1;len<(n<<1);len<<=1)
        {
            lim=len<<1;
            for(int i=0;i<len;i++)A[i]=a[i];
            inv(b,B,lim>>1);
            for(int i=0;i<lim;i++)R[i]=(R[i>>1]>>1)|((i&1)?len:0);
            NTT(A,lim,1);NTT(B,lim,1);
            for(int i=0;i<lim;i++)A[i]=1ll*A[i]*B[i]%mod;
            NTT(A,lim,-1);
            for(int i=0;i<len;i++)b[i]=1ll*(b[i]+A[i])%mod*inv2%mod;
            for(int i=len;i<lim;i++)b[i]=0;
        }
        for(int i=0;i<len;i++)A[i]=B[i]=0;
        for(int i=n;i<len;i++)b[i]=0;
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)scanf("%d",&f[i]);
        Sqrt(f,g,n);
        for(int i=0;i<n;i++)printf("%d ",g[i]);
    }

    多项式求lnhttps://www.luogu.org/problemnew/show/P4725

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4e5+7,mod=998244353,inv2=499122177;
    int n,nn,L,a[N],b[N],c[N],d[N],inv[N],R[N];
    int qpow(int a,int b)
    {
        int ret=1;
        while(b)
        {
            if(b&1)ret=1ll*ret*a%mod;
            a=1ll*a*a%mod,b>>=1;
        }
        return ret;
    }
    void NTT(int*a,int f)
    {
        for(int i=0;i<nn;i++)if(i<R[i])swap(a[i],a[R[i]]);
        for(int i=1;i<nn;i<<=1)
        {
            int wn=qpow(3,mod/(i<<1));
            if(f==-1)wn=qpow(wn,mod-2);
            for(int j=0;j<nn;j+=i<<1)
            for(int k=0,w=1;k<i;k++,w=1ll*w*wn%mod)
            {
                int x=a[j+k],y=1ll*a[i+j+k]*w%mod;
                a[j+k]=(x+y)%mod,a[i+j+k]=(x-y+mod)%mod;
            }
        }
        if(f==1)return;
        int invn=qpow(nn,mod-2);
        for(int i=0;i<nn;i++)a[i]=1ll*a[i]*invn%mod;
    }
    void getinv(int*a,int*b,int n)
    {
        if(n==1){b[0]=qpow(a[0],mod-2);return;}
        getinv(a,b,n+1>>1);
        nn=1,L=0;while(nn<(n<<1))nn<<=1,L++;
        for(int i=0;i<nn;i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
        for(int i=0;i<nn;i++)c[i]=i<n?a[i]:0;
        for(int i=n+1>>1;i<nn;i++)b[i]=0;
        NTT(b,1),NTT(c,1);
        for(int i=0;i<nn;i++)b[i]=(mod+2-1ll*b[i]*c[i]%mod)%mod*b[i]%mod;
        NTT(b,-1);
        for(int i=n;i<nn;i++)b[i]=0;
    }
    void getln(int*a,int*b,int n)
    {
        getinv(a,b,n);
        nn=1,L=0;while(nn<(n<<1))nn<<=1,L++;
        for(int i=0;i<nn;i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
        for(int i=0;i<n-1;i++)d[i]=1ll*a[i+1]*(i+1)%mod;
        for(int i=n-1;i<nn;i++)d[i]=0;
        NTT(b,1),NTT(d,1);
        for(int i=0;i<nn;i++)b[i]=1ll*b[i]*d[i]%mod;
        NTT(b,-1);
        for(int i=n-1;i>0;i--)b[i]=1ll*b[i-1]*inv[i]%mod;
        for(int i=n;i<nn;i++)b[i]=0;
        b[0]=0;
    }
    int main()
    {
        scanf("%d",&n);for(int i=0;i<n;i++)scanf("%d",&a[i]);
        inv[1]=1;for(int i=2;i<=n;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
        getln(a,b,n);
        for(int i=0;i<n;i++)printf("%d ",b[i]);
    }

    多项式求exp(其实前面求ln全部包含于此了)https://www.luogu.org/problemnew/show/P4726

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4e5+7,mod=998244353,inv2=499122177;
    int n,nn,L,a[N],b[N],c[N],d[N],lnb[N],inv[N],R[N];
    int qpow(int a,int b)
    {
        int ret=1;
        while(b)
        {
            if(b&1)ret=1ll*ret*a%mod;
            a=1ll*a*a%mod,b>>=1;
        }
        return ret;
    }
    void NTT(int*a,int f)
    {
        for(int i=0;i<nn;i++)if(i<R[i])swap(a[i],a[R[i]]);
        for(int i=1;i<nn;i<<=1)
        {
            int wn=qpow(3,mod/(i<<1));
            if(f==-1)wn=qpow(wn,mod-2);
            for(int j=0;j<nn;j+=i<<1)
            for(int k=0,w=1;k<i;k++,w=1ll*w*wn%mod)
            {
                int x=a[j+k],y=1ll*a[i+j+k]*w%mod;
                a[j+k]=(x+y)%mod,a[i+j+k]=(x-y+mod)%mod;
            }
        }
        if(f==1)return;
        int invn=qpow(nn,mod-2);
        for(int i=0;i<nn;i++)a[i]=1ll*a[i]*invn%mod;
    }
    void getinv(int*a,int*b,int n)
    {
        if(n==1){b[0]=qpow(a[0],mod-2);return;}
        getinv(a,b,n+1>>1);
        nn=1,L=0;while(nn<(n<<1))nn<<=1,L++;
        for(int i=0;i<nn;i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
        for(int i=0;i<nn;i++)c[i]=i<n?a[i]:0;
        for(int i=n+1>>1;i<nn;i++)b[i]=0;
        NTT(b,1),NTT(c,1);
        for(int i=0;i<nn;i++)b[i]=(mod+2-1ll*b[i]*c[i]%mod)%mod*b[i]%mod;
        NTT(b,-1);
        for(int i=n;i<nn;i++)b[i]=0;
    }
    void getln(int*a,int*b,int n)
    {
        getinv(a,b,n);
        nn=1,L=0;while(nn<(n<<1))nn<<=1,L++;
        for(int i=0;i<nn;i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
        for(int i=0;i<n-1;i++)d[i]=1ll*a[i+1]*(i+1)%mod;
        for(int i=n-1;i<nn;i++)d[i]=0;
        NTT(b,1),NTT(d,1);
        for(int i=0;i<nn;i++)b[i]=1ll*b[i]*d[i]%mod;
        NTT(b,-1);
        for(int i=n-1;i>0;i--)b[i]=1ll*b[i-1]*inv[i]%mod;
        for(int i=n;i<nn;i++)b[i]=0;
        b[0]=0;
    }
    void getexp(int*a,int*b,int n)
    {
        if(n==1){b[0]=1;return;}
        getexp(a,b,(n+1)>>1);
        getln(b,lnb,n);
        nn=1,L=0;while(nn<(n<<1))nn<<=1,L++;
        for(int i=0;i<nn;i++)R[i]=(R[i>>1]>>1)|((i&1)<<L-1);
        for(int i=0;i<n;i++)lnb[i]=a[i]>=lnb[i]?a[i]-lnb[i]:a[i]-lnb[i]+mod;
        for(int i=n;i<nn;i++)lnb[i]=b[i]=0;
        lnb[0]++;
        NTT(b,1),NTT(lnb,1);
        for(int i=0;i<nn;i++)b[i]=1ll*b[i]*lnb[i]%mod;
        NTT(b,-1);
        for(int i=n;i<nn;i++)b[i]=0;
    }
    int main()
    {
        scanf("%d",&n);for(int i=0;i<n;i++)scanf("%d",&a[i]);
        inv[1]=1;for(int i=2;i<=n;i++)inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
        getexp(a,b,n);
        for(int i=0;i<n;i++)printf("%d ",b[i]);
    }

    咕了

  • 相关阅读:
    第一课 进阶高手的大门
    Codeforces Round #363 (Div. 2) C. Vacations
    HDU 5718 Oracle
    A
    Fibonacci数的后9位
    UESTC 982质因子分解
    UESTC149 解救小Q
    UESTC93 King's Sanctuary
    HDU 4857 逃生
    L1-006. 连续因子
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/10978121.html
Copyright © 2020-2023  润新知