zoukankan      html  css  js  c++  java
  • 模板------模板

    多项式算法:

      FFT:

    #include<bits/stdc++.h>
    using namespace std;
    int read()
    {
        int x=0,f=1;    char ch=getchar();
        while(ch<'0'||ch>'9')    {if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')    {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*f;
    }
    const int N=3000050;
    const double pi=acos(-1.0);
    int n,m,limit=1,s,pos[N];
    struct node
    {
        double x,y;
        node (double xx=0,double yy=0)    {x=xx;y=yy;}
    }a[N],b[N];
    node operator + (node a,node b){return node(a.x+b.x,a.y+b.y);}
    node operator - (node a,node b){return node(a.x-b.x,a.y-b.y);}
    node operator * (node a,node b){return node(a.x*b.x-a.y*b.y,a.x*b.y+a.y*b.x);}
    void FFT(node *nw,int opt)
    {
        for(int i=0;i<limit;++i)
            if(i<pos[i])    swap(nw[i],nw[pos[i]]);
        for(int mid=1;mid<limit;mid<<=1)
        {
            node base(cos(pi/mid),opt*sin(pi/mid));
            for(int len=mid<<1,i=0;i<limit;i+=len)
            {
                node w(1,0);
                for(int j=0;j<mid;++j,w=w*base)
                {
                    node x=nw[i+j];    node y=nw[i+j+mid]*w;
                    nw[i+j]=x+y;    nw[i+j+mid]=x-y;
                }
            }
        }
    }
    int main()
    {
        n=read();    m=read();
        for(int i=0;i<=n;++i)    a[i].x=read();
        for(int i=0;i<=m;++i)    b[i].x=read();
        while(limit<=n+m)    limit<<=1,s++;
        for(int i=1;i<limit;++i)    pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1));
        FFT(a,1);    FFT(b,1);
        for(int i=0;i<limit;++i)    a[i]=a[i]*b[i];
        FFT(a,-1);
        for(int i=0;i<=n+m;++i)    printf("%d ",(int)(a[i].x/limit+0.5));
        return 0;
    }
    View Code

      NTT:

    #include<bits/stdc++.h>
    #define ll long long 
    using namespace std;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9')    {if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')    {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*f;
    }
    const int N=3000050;
    const int p=998244353;
    int n,m,limit=1,s;
    int pos[N],a[N],b[N];
    int ksm(int u,int v)
    {
        int sum=1;
        while(v)
        {
            if(v&1)    sum=(ll)sum*u%p;
            v>>=1;    u=(ll)u*u%p;
        }
        return sum;
    }
    void FNT(int *nw,int opt)
    {
        for(int i=0;i<limit;++i)
            if(i<pos[i])    swap(nw[i],nw[pos[i]]);
        for(int mid=1;mid<limit;mid<<=1)
        {
            int base=ksm(3,(p-1)/(mid<<1));
            if(opt==-1)    base=ksm(base,p-2);
            for(int len=mid<<1,i=0;i<limit;i+=len)
            {
                int w=1;
                for(int j=0;j<mid;++j,w=(ll)w*base%p)
                {
                    int x=nw[i+j];    int y=(ll)w*nw[i+j+mid]%p;
                    nw[i+j]=(x+y)%p;    nw[i+j+mid]=(x-y+p)%p;
                }
            }
        }
    }
    int main()
    {
        n=read();    m=read();
        for(int i=0;i<=n;++i)    a[i]=read();
        for(int i=0;i<=m;++i)    b[i]=read();
        while(limit<=n+m)    limit<<=1,s++;
        for(int i=0;i<limit;++i)    pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1));
        FNT(a,1);    FNT(b,1);
        for(int i=0;i<limit;++i)    a[i]=(ll)a[i]*b[i]%p;
        FNT(a,-1);    int inv=ksm(limit,p-2);
        for(int i=0;i<=n+m;++i)    printf("%d ",(ll)a[i]*inv%p);
        return 0;
    }
    View Code

       FWT:

    #include<bits/stdc++.h>
    #define ll long long
    #define p 998244353
    using namespace std;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9')    {if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')    {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        return x*f;
    }
    int n,inv;
    int a[1000050],b[1000050],c[1000050];
    int ksm(int u,int v)
    {
        int sum=1;
        while(v)
        {
            if(v&1)    sum=(ll)sum*u%p;
            v>>=1;    u=(ll)u*u%p;
        }
        return sum;
    }
    void FWTOR(int *nw,int opt)
    {
        for(int mid=1;mid<n;mid<<=1)
            for(int len=mid<<1,i=0;i<n;i+=len)
                for(int j=0;j<mid;++j)
                    if(opt==1)    nw[i+j+mid]=(nw[i+j]+nw[i+j+mid])%p;
                    else    nw[i+j+mid]=(nw[i+j+mid]-nw[i+j]+p)%p;
    }
    void FWTAND(int *nw,int opt)
    {
        for(int mid=1;mid<n;mid<<=1)
            for(int len=mid<<1,i=0;i<n;i+=len)
                for(int j=0;j<mid;++j)
                    if(opt==1)    nw[i+j]=(nw[i+j]+nw[i+j+mid])%p;
                    else    nw[i+j]=(nw[i+j]-nw[i+j+mid]+p)%p;
    }
    void FWTXOR(int *nw,int opt)
    {
        for(int mid=1;mid<n;mid<<=1)
            for(int len=mid<<1,i=0;i<n;i+=len)
                for(int j=0;j<mid;++j)
                {
                    int x=nw[i+j];    int y=nw[i+j+mid];
                    if(opt==1)    nw[i+j]=(x+y)%p,nw[i+j+mid]=(x-y+p)%p;
                    else    nw[i+j]=(ll)(x+y)*inv%p,nw[i+j+mid]=(ll)(x-y+p)*inv%p;
                        
                }
    }
    int main()
    {
        n=1<<read();    inv=ksm(2,p-2);
        for(int i=0;i<n;++i)    a[i]=read();
        for(int i=0;i<n;++i)    b[i]=read();
        FWTOR(a,1);        FWTOR(b,1);
        for(int i=0;i<n;++i)    c[i]=(ll)a[i]*b[i]%p;
        FWTOR(a,-1);    FWTOR(b,-1);    FWTOR(c,-1);
        for(int i=0;i<n;++i)    printf("%d ",c[i]);    puts(" ");
        FWTAND(a,1);    FWTAND(b,1);
        for(int i=0;i<n;++i)    c[i]=(ll)a[i]*b[i]%p;
        FWTAND(a,-1);    FWTAND(b,-1);    FWTAND(c,-1);
        for(int i=0;i<n;++i)    printf("%d ",c[i]);    puts(" ");
        FWTXOR(a,1);    FWTXOR(b,1);
        for(int i=0;i<n;++i)    c[i]=(ll)a[i]*b[i]%p;
        FWTXOR(a,-1);FWTXOR(b,-1);    FWTXOR(c,-1);
        for(int i=0;i<n;++i)    printf("%d ",c[i]);    puts(" ");
        return 0;
    }
    View Code

      多项式求逆:

    #include<bits/stdc++.h>
    #define ll long long
    #define p 998244353
    using namespace std;
    int read()
    {
        int x=0,f=1;    char ch=getchar();
        while(ch<'0'||ch>'9')    {if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')    {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
        return x*f;
    }
    const int N=400050;
    int n,len,limit,s;
    int f[N],g[N],a[N],b[N];
    int pos[N];
    int ksm(int u,int v)
    {
        int sum=1;
        while(v)
        {
            if(v&1)    sum=(ll)sum*u%p;
            v>>=1;    u=(ll)u*u%p;
        }
        return sum;
    }
    void NTT(int *nw,int opt)
    {
        for(int i=0;i<limit;++i)
            if(i<pos[i])    swap(nw[i],nw[pos[i]]);
        for(int mid=1;mid<limit;mid<<=1)
        {
            int base=ksm(3,(p-1)/(mid<<1));
            if(opt==-1)    base=ksm(base,p-2);
            for(int len=mid<<1,i=0;i<limit;i+=len)
            {
                int w=1;
                for(int j=0;j<mid;++j,w=(ll)w*base%p)
                {
                    int x=nw[i+j];    int y=(ll)w*nw[i+j+mid]%p;
                    nw[i+j]=(x+y)%p;    nw[i+j+mid]=(x-y+p)%p;
                }
            }
        }
    }
    int main()
    {
        n=read()-1;
        for(int i=0;i<=n;++i)    f[i]=read();
        limit=2;    len=1;    s=1;    g[0]=ksm(f[0],p-2);
        while(len<=n)
        {
            limit<<=1;    len<<=1;    s++;
            for(int i=0;i<limit;++i)    pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1));
            for(int i=0;i<len;++i)    a[i]=f[i],b[i]=g[i];
            NTT(a,1);    NTT(b,1);
            for(int i=0;i<limit;++i)    a[i]=((ll)2*b[i]%p-(ll)a[i]*b[i]%p*b[i]%p+p)%p;
            NTT(a,-1);    int inv=ksm(limit,p-2);
            for(int i=0;i<len;++i)    g[i]=(ll)a[i]*inv%p;
        }
        for(int i=0;i<=n;++i)    printf("%d ",g[i]);
        return 0;
    }
    View Code

      多项式开根(求逆,开根):

    #include<bits/stdc++.h>
    #define ll long long
    #define p 998244353
    using namespace std;
    int read()
    {
        int x=0,f=1;    char ch=getchar();
        while(ch<'0'||ch>'9')    {if(ch=='-')    f=-1;    ch=getchar();}
        while(ch>='0'&&ch<='9')    {x=(x<<3)+(x<<1)+(ch^48);    ch=getchar();}
        return x*f;
    }
    int n,m,inv2;
    int limit,s,pos[400050];
    int f[400050],g[400050],h[400050];
    int a_[400050],b_[400050],c_[400050];
    int a__[400050],b__[400050],c__[400050],d__[400050];
    int ksm(int u,int v)
    {
        int sum=1;
        while(v)
        {
            if(v&1)    sum=(ll)sum*u%p;
            v>>=1;    u=(ll)u*u%p;
        }
        return sum;
    }
    void fir(int len)
    {
        limit=1;    s=0;
        while(limit<=len+len)    limit<<=1,s++;
        for(int i=0;i<limit;++i)    pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1));
    }
    void NTT(int *nw,int opt)
    {
        for(int i=0;i<limit;++i)
            if(i<pos[i])    swap(nw[i],nw[pos[i]]);
        for(int mid=1;mid<limit;mid<<=1)
        {
            int base=ksm(3,(p-1)/(mid<<1));
            if(opt==-1)    base=ksm(base,p-2);
            for(int len=mid<<1,i=0;i<limit;i+=len)
            {
                int w=1;
                for(int j=0;j<mid;++j,w=(ll)w*base%p)
                {
                    int x=nw[i+j];    int y=(ll)w*nw[i+j+mid]%p;
                    nw[i+j]=(x+y)%p;    nw[i+j+mid]=(x-y+p)%p;
                }
            }
        }
    }
    void INV(int *A,int *B,int N)
    {
        int len=1;    B[0]=ksm(A[0],p-2);
        while(len<=N)
        {
            len<<=1;    fir(len-1);
            for(int i=0;i<limit;++i)    a_[i]=b_[i]=0;
            for(int i=0;i<len;++i)    a_[i]=A[i],b_[i]=B[i];
            NTT(a_,1);    NTT(b_,1);
            for(int i=0;i<limit;++i)    c_[i]=((ll)2*b_[i]%p-(ll)a_[i]*b_[i]%p*b_[i]%p+p)%p;
            NTT(c_,-1);    int inv=ksm(limit,p-2);
            for(int i=0;i<len;++i)    B[i]=(ll)c_[i]*inv%p;
        }
    }
    void SQRT(int *A,int *B,int N)
    {
        int len=1;    B[0]=1;
        while(len<=N)
        {
            len<<=1;    fir(len-1);
            for(int i=0;i<limit;++i)    a__[i]=b__[i]=c__[i]=0;
            for(int i=0;i<len;++i)    a__[i]=A[i],b__[i]=B[i];
            INV(b__,c__,len-1);    NTT(a__,1);    NTT(b__,1);    NTT(c__,1);
            for(int i=0;i<limit;++i)        d__[i]=(ll)((ll)a__[i]+(ll)b__[i]*b__[i]%p)%p*inv2%p*c__[i]%p;
            NTT(d__,-1);    int inv=ksm(limit,p-2);
            for(int i=0;i<len;++i)    B[i]=(ll)d__[i]*inv%p;
        }
    }
    int main()
    {
        n=read()-1;    inv2=ksm(2,p-2);
        for(int i=0;i<=n;++i)    f[i]=read();    
        SQRT(f,g,n);
        for(int i=0;i<=n;++i)    printf("%d ",g[i]);
        return 0;
    }
    View Code

      多项式除法(求逆,除法,取模):

    #include<bits/stdc++.h>
    #define ll long long
    #define p 998244353
    using namespace std;
    int read()
    {
        int x=0,f=1;    char ch=getchar();
        while(ch<'0'||ch>'9')    {if(ch=='-')    f=-1;    ch=getchar();}
        while(ch>='0'&&ch<='9')    {x=(x<<3)+(x<<1)+(ch^48);    ch=getchar();}
        return x*f;
    }
    const int N=2000050;
    int n,m,nm;
    int limit,s,pos[N];
    int f[N],g[N],h[N];
    int val[N],ans[N];
    int a[N],b[N],c[N];
    int _a[N],_b[N],_c[N];
    int __a[N],__b[N],__c[N],__d[N];
    void fir(int len)
    {
        limit=1;s=0;
        while(limit<=len)    limit<<=1,s++;
        for(int i=0;i<limit;++i)    pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1));
    }
    int ksm(int u,int v)
    {
        int sum=1;
        while(v)
        {
            if(v&1)    sum=(ll)sum*u%p;
            v>>=1;    u=(ll)u*u%p;
        }
        return sum;
    }
    void NTT(int *nw,int opt)
    {
        for(int i=0;i<limit;++i)
            if(i<pos[i])    swap(nw[i],nw[pos[i]]);
        for(int mid=1;mid<limit;mid<<=1)
        {
            int base=ksm(3,(p-1)/(mid<<1));
            if(opt==-1)    base=ksm(base,p-2);
            for(int len=mid<<1,i=0;i<limit;i+=len)
            {
                int w=1;
                for(int j=0;j<mid;j++,w=(ll)w*base%p)
                {
                    int x=nw[i+j];    int y=(ll)w*nw[i+j+mid]%p;
                    nw[i+j]=(x+y)%p;    nw[i+j+mid]=(x-y+p)%p;
                }
            }
        }
    }
    void MUL(int *A,int *B,int *C,int N,int M)
    {
        fir(N+M);
        for(int i=0;i<limit;++i)    a[i]=b[i]=0;
        for(int i=0;i<=N;++i)    a[i]=A[i];
        for(int i=0;i<=M;++i)    b[i]=B[i];
        NTT(a,1);    NTT(b,1);
        for(int i=0;i<limit;++i)    c[i]=(ll)a[i]*b[i]%p;
        NTT(c,-1);    int inv=ksm(limit,p-2);
        for(int i=0;i<=N+M;++i)        C[i]=(ll)c[i]*inv%p;
    }
    void INV(int *A,int *B,int N)
    {
        int len=1;    _c[0]=ksm(A[0],p-2);    _c[1]=0;
        while(len<=N)
        {
            len<<=1;    fir(len+len-1);
            for(int i=0;i<limit;++i)    _a[i]=_b[i]=0;
            for(int i=0;i<len;++i)    _a[i]=A[i],_b[i]=_c[i];
            NTT(_a,1);    NTT(_b,1);
            for(int i=0;i<limit;++i)    _c[i]=((ll)_b[i]*2-(ll)_a[i]*_b[i]%p*_b[i]%p+p)%p;
            NTT(_c,-1);    int inv=ksm(limit,p-2);
            for(int i=0;i<len;++i)    _c[i]=(ll)_c[i]*inv%p;
            for(int i=len;i<limit;++i)    _c[i]=0;
        }
        for(int i=0;i<=N;++i)    B[i]=_c[i];
    }
    void MOD(int *A,int *B,int *C,int N,int M)
    {
        fir(N+N);
        for(int i=0;i<limit;++i)    __a[i]=__b[i]=0;
        for(int i=0;i<=N;++i)    __a[i]=A[N-i];
        for(int i=0;i<=M;++i)    __b[i]=B[M-i];
        INV(__b,__b,N-M);    MUL(__a,__b,__c,N,N-M);    reverse(__c,__c+N-M+1);
        for(int i=0;i<=N;++i)    __a[i]=A[i];
        for(int i=0;i<=M;++i)    __b[i]=B[i];
        for(int i=0;i<=N-M;++i)    cout<<__c[i]<<" ";    cout<<endl;
        MUL(__b,__c,__d,M,N-M);
        for(int i=0;i<M;++i)    C[i]=(__a[i]-__d[i]+p)%p;
        for(int i=0;i<M;++i)    cout<<C[i]<<" ";
    }
    int main()
    {
        n=read();    m=read();
        for(int i=0;i<=n;++i)    f[i]=read();
        for(int i=0;i<=m;++i)    g[i]=read();
        MOD(f,g,h,n,m);
        return 0;
    }
    View Code

      多项式快速幂(对数,指数):

    #include<bits/stdc++.h>
    #define ll long long
    #define p 998244353
    using namespace std;
    const int N=400050;
    int read()
    {
        ll x=0,f=1;    char ch=getchar();
        while(ch<'0'||ch>'9')    {if(ch=='-')    f=-1;    ch=getchar();}
        while(ch>='0'&&ch<='9')    {x=((x<<3)+(x<<1)+(ch^48))%p;    ch=getchar();};
        return (int)x*f;
    }
    int n,m,inv2;
    int limit,s,pos[N];
    int f[N],g[N],h[N];
    int a[N],b[N],c[N];
    int _a[N],_b[N],_c[N],_ans[N];
    int __a[N],__b[N],__c[N];
    int ___a[N],___b[N],___c[N],___d[N],___ans[N];
    int ksm(int u,int v)
    {
        int sum=1;
        while(v)
        {
            if(v&1)    sum=(ll)sum*u%p;
            v>>=1;    u=(ll)u*u%p;
        }
        return sum;
    }
    void fir(int len)
    {
        limit=1;    s=0;
        while(limit<=len)    limit<<=1,s++;
        for(int i=0;i<limit;++i)    pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1));
    }
    void NTT(int *nw,int opt)
    {
        for(int i=0;i<limit;++i)
            if(i<pos[i])    swap(nw[i],nw[pos[i]]);
        for(int mid=1;mid<limit;mid<<=1)
        {
            int base=ksm(3,(p-1)/(mid<<1));
            if(opt==-1)    base=ksm(base,p-2);
            for(int len=mid<<1,i=0;i<limit;i+=len)
            {
                int w=1;
                for(int j=0;j<mid;++j,w=(ll)w*base%p)
                {
                    int x=nw[i+j];    int y=(ll)w*nw[i+j+mid]%p;
                    nw[i+j]=(x+y)%p;    nw[i+j+mid]=(x-y+p)%p;
                }
            }
        }
    }
    void DIREV(int *A,int *B,int N)
    {
        for(int i=0;i<N;++i)
            B[i]=(ll)A[i+1]*(i+1)%p;
        B[n]=0;
    }
    void INTER(int *A,int *B,int N)
    {
        for(int i=N;i>=1;--i)
            B[i]=(ll)A[i-1]*ksm(i,p-2)%p;
        B[0]=0;
    }
    void MUL(int *A,int *B,int *C,int N)
    {
        fir(N+N);
        for(int i=0;i<limit;++i)    a[i]=b[i]=0;
        for(int i=0;i<=N;++i)    a[i]=A[i],b[i]=B[i];
        NTT(a,1);    NTT(b,1);
        for(int i=0;i<limit;++i)    c[i]=(ll)a[i]*b[i]%p;
        NTT(c,-1);    int inv=ksm(limit,p-2);
        for(int i=0;i<=N+N;++i)        C[i]=(ll)c[i]*inv%p;
    }
    void INV(int *A,int *B,int N)
    {
        int len=1;    _ans[0]=ksm(A[0],p-2);    _ans[1]=0;
        while(len<=N)
        {
            len<<=1;    fir(len+len-1);
            for(int i=0;i<limit;++i)    _a[i]=_b[i]=0;
            for(int i=0;i<len;++i)    _a[i]=A[i],_b[i]=_ans[i];
            NTT(_a,1);    NTT(_b,1);
            for(int i=0;i<limit;++i)    _c[i]=((ll)2*_b[i]%p-(ll)_a[i]*_b[i]%p*_b[i]%p+p)%p;
            NTT(_c,-1);    int inv=ksm(limit,p-2);
            for(int i=0;i<len;++i)    _ans[i]=(ll)_c[i]*inv%p;
            for(int i=len;i<limit;++i)    _ans[i]=0;
        }
        for(int i=0;i<=N;++i)    B[i]=_ans[i];
    }
    void LN(int *A,int *B,int N)
    {
        for(int i=0;i<=N;++i)    __a[i]=A[i];
        INV(__a,__b,N);    DIREV(__a,__c,N);
        MUL(__b,__c,__a,N);    INTER(__a,__a,N);
        for(int i=0;i<=N;++i)    B[i]=__a[i];
    }
    void EXP(int *A,int *B,int N)
    {
        int len=1;    ___ans[0]=1;    ___ans[1]=0;
        while(len<=N)
        {
            len<<=1;
            LN(___ans,___a,len-1);    ___a[0]=(___a[0]-1+p)%p;
            for(int i=0;i<len;++i)    ___a[i]=(p-___a[i]+A[i])%p;
            MUL(___ans,___a,___ans,len-1);
            for(int i=len;i<limit;++i)    ___ans[i]=0;
        }
        for(int i=0;i<=N;++i)    B[i]=___ans[i];
    }
    int main()
    {
        n=read()-1;    m=read();
        for(int i=0;i<=n;++i)    f[i]=read();
        LN(f,f,n);
        for(int i=0;i<=n;++i)    f[i]=(ll)m*f[i]%p;
        EXP(f,f,n);
        for(int i=0;i<=n;++i)    printf("%d ",f[i]);
        return 0;
    }
    View Code

      多项式多点求值:

    #include<bits/stdc++.h>
    #define ll long long
    #define p 998244353
    using namespace std;
    int read()
    {
        int x=0,f=1;    char ch=getchar();
        while(ch<'0'||ch>'9')    {if(ch=='-')    f=-1;    ch=getchar();}
        while(ch>='0'&&ch<='9')    {x=(x<<3)+(x<<1)+(ch^48);    ch=getchar();}
        return x*f;
    }
    const int N=4000050;
    int n,m,LIMIT,S,SUM;
    int limit,s,pos[N];
    int val[N],ans[N];
    int aa[N],ab[N],ac[N];
    int ba[N],bb[N],bc[N];
    int ca[N],cb[N],cc[N],cd[N];
    int t[16][N],f[N],g[N],h[N],r[N];
    int w[N],iw[N],inv[N];
    int add(int x,int y){    return x+y>p? x+y-p:x+y;}
    int mul(int x,int y){    return (ll)x*y-(ll)x*y/p*p;}
    void fir(int len)
    {
        limit=1;    s=0;
        while(limit<=len)    limit<<=1,s++;
        for(int i=0;i<limit;++i)    pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1));
    }
    int ksm(int u,int v)
    {
        int sum=1;
        while(v)
        {
            if(v&1)    sum=mul(sum,u);
            v>>=1;    u=mul(u,u);
        }
        return sum;
    }
    void NTT(int *nw,int *W)
    {
        for(int i=0;i<limit;++i)
            if(i<pos[i])    swap(nw[i],nw[pos[i]]);
        for(int mid=1;mid<limit;mid<<=1)
        {
            int base=LIMIT/mid;
            for(int len=mid<<1,i=0;i<limit;i+=len)
            {
                int k=0;
                for(int j=0;j<mid;j++,k+=base)
                {
                    int x=nw[i+j];    int y=mul(W[k],nw[i+j+mid]);
                    nw[i+j]=add(x,y);    nw[i+j+mid]=add(x,p-y);
                }
            }
        }
    }
    void MUL(int *A,int *B,int *C,int N,int M,int *a=aa,int *b=ab,int *c=ac)
    {
        fir(N+M);
        for(int i=0;i<limit;++i)    a[i]=b[i]=0;
        for(int i=0;i<=N;++i)    a[i]=A[i];
        for(int i=0;i<=M;++i)    b[i]=B[i];
        NTT(a,w);    NTT(b,w);
        for(int i=0;i<limit;++i)    c[i]=mul(a[i],b[i]);
        NTT(c,iw);
        for(int i=0;i<=N+M;++i)        C[i]=mul(c[i],inv[s]);
    }
    void INV(int *A,int *B,int N,int *a=ba,int *b=bb,int *c=bc)
    {
        int len=1;    c[0]=ksm(A[0],p-2);    c[1]=0;
        while(len<=N)
        {
            len<<=1;    fir(len);
            for(int i=0;i<limit;++i)    a[i]=b[i]=0;
            for(int i=0;i<len;++i)    a[i]=A[i],b[i]=c[i];
            NTT(a,w);    NTT(b,w);
            for(int i=0;i<limit;++i)    c[i]=add(mul(b[i],2),p-mul(a[i],mul(b[i],b[i])));
            NTT(c,iw);
            for(int i=0;i<len;++i)    c[i]=mul(c[i],inv[s]);;
            for(int i=len;i<limit;++i)    c[i]=0;
        }
        for(int i=0;i<=N;++i)    B[i]=c[i];
    }
    void MOD(int *A,int *B,int *C,int N,int M,int *a=ca,int *b=cb,int *c=cc,int *d=cd)
    {
        fir(N+N);
        for(int i=0;i<limit;++i)    a[i]=b[i]=0;
        for(int i=0;i<=N;++i)    a[i]=A[N-i];
        for(int i=0;i<=M;++i)    b[i]=B[M-i];
        INV(b,b,N-M);    MUL(a,b,c,N,N-M);    reverse(c,c+N-M+1);
        for(int i=0;i<=N;++i)    a[i]=A[i];
        for(int i=0;i<=M;++i)    b[i]=B[i];
        MUL(b,c,d,M,N-M);
        for(int i=0;i<M;++i)    C[i]=add(a[i],p-d[i]);
    }
    void calc()
    {
        w[0]=iw[0]=1;    fir(n+n);    LIMIT=limit>>1;    S=s-1;
        for(int i=1;i<limit;++i)    w[i]=ksm(3,(p-1)/limit*i);
        for(int i=1;i<limit;++i)    iw[i]=ksm(w[i],p-2);
        for(int i=0;i<=s;++i)    inv[i]=ksm(1<<i,p-2);
        for(int i=0;i<LIMIT;++i)    t[0][i]=p-1;
        for(int mid=1,lg=0;mid<LIMIT/2;mid<<=1,lg++)
        {
            for(int len=mid<<1,i=0;i<LIMIT;i+=len)
            {
                f[0]=g[0]=1;
                for(int j=0;j<mid;++j)    f[j+1]=t[lg][i+j];
                for(int j=0;j<mid;++j)    g[j+1]=t[lg][i+j+mid];
                for(int j=0;j<mid;++j)    f[0]=mul(f[0],val[i+j]);
                for(int j=0;j<mid;++j)    g[0]=mul(g[0],val[i+j+mid]);
                MUL(f,g,h,mid,mid);
                for(int j=0;j<len;++j)    t[lg+1][i+j]=h[j+1];
            }
        }
    }
    void solve()
    {
        for(int mid=LIMIT/2,lg=S-1;mid>=1;mid>>=1,lg--)
            for(int len=mid<<1,i=0;i<LIMIT;i+=len)
            {
                f[0]=g[0]=1;
                for(int j=0;j<len;++j)    h[j]=ans[i+j];
                for(int j=0;j<mid;++j)    f[j+1]=t[lg][i+j];
                for(int j=0;j<mid;++j)    g[j+1]=t[lg][i+j+mid];
                for(int j=0;j<mid;++j)    f[0]=mul(f[0],val[i+j]);
                for(int j=0;j<mid;++j)    g[0]=mul(g[0],val[i+j+mid]);
                MOD(h,f,r,len-1,mid);
                for(int j=0;j<mid;++j)    ans[i+j]=r[j];
                MOD(h,g,r,len-1,mid);
                 for(int j=0;j<mid;++j)    ans[i+j+mid]=r[j];
            }
    }
    int main()
    {
        n=read();    m=read();
        for(int i=0;i<=n;++i)    ans[i]=read();
        for(int i=1;i<=m;++i)    val[i]=read();
        calc();    solve();
        for(int i=1;i<=m;++i)    printf("%d
    ",ans[i]);
        return 0;
    }
    View Code

    字符串算法:

       后缀数组:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m;
    char s[1000050];
    int height[2000050];
    int sa[2000050],sb[2000050];
    int rk[2000050],t[2000050],tot,top;
    void qsort()
    {
        for(int i=0;i<=m;i++)    t[i]=0;
        for(int i=1;i<=n;i++)    t[rk[i]]++;
        for(int i=1;i<=m;++i)    t[i]+=t[i-1];
        for(int i=n;i>=1;--i)    sa[t[rk[sb[i]]]--]=sb[i];
    }
    void calc_sa()
    {
        for(int i=1;i<=n;++i)    sb[i]=i;
        for(int i=1;i<=n;++i)    rk[i]=s[i];
        for(int i=1;i<=n;++i)    m=max(m,rk[i]);
        qsort();
        for(int k=1;tot<n;k<<=1)
        {
            tot=top=0;
            for(int i=1;i<=k;++i)    sb[++top]=n-k+i;
            for(int i=1;i<=n;++i)    if(sa[i]>k)    sb[++top]=sa[i]-k;
            qsort();    swap(rk,sb);    rk[sa[1]]=++tot;
            for(int i=2;i<=n;++i)
            {
                if(sb[sa[i]]!=sb[sa[i-1]]||sb[sa[i]+k]!=sb[sa[i-1]+k])    ++tot;
                rk[sa[i]]=tot;
            }
            m=tot;
        }
    }
    void calc_height()
    {
        for(int i=1,j,k=0;i<=n;++i)
        {
            j=sa[rk[i]-1];    if(k)    --k;
            while(s[i+k]==s[j+k])    ++k;
            height[rk[i]]=k;
        }
    }
    int main()
    {
        scanf("%s",s+1);    n=strlen(s+1);    calc_sa();    calc_height();
        for(int i=1;i<=n;++i)    printf("%d ",sa[i]);    puts(" ");
        for(int i=1;i<=n;++i)    printf("%d ",height[i]);
        return 0;
    }
    View Code

     数论:

      第一类斯特林数(行):

    #include<bits/stdc++.h>
    #define ll long long
    #define p 167772161
    using namespace std;
    int n,limit,s;
    int fac[1000050];
    int fav[1000050];
    int tmp[1000050];
    int pos[1000050];
    int ans[1000050];
    int a[1000050];
    int b[1000050];
    int c[1000050];
    int ksm(int u,int v)
    {
        int sum=1;
        while(v)
        {
            if(v&1)    sum=(ll)sum*u%p;
            v>>=1;    u=(ll)u*u%p;
        }
        return sum;
    }
    void fir(int len)
    {
        limit=1;    s=0;
        while(limit<=(len<<1))    limit<<=1,s++;
        for(int i=0;i<limit;++i)    pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1));
    }
    void NTT(int *nw,int opt)
    {
        for(int i=0;i<limit;++i)
            if(i<pos[i])    swap(nw[i],nw[pos[i]]);
        for(int mid=1;mid<limit;mid<<=1)
        {
            int base=ksm(3,(p-1)/(mid<<1));
            if(opt==-1)    base=ksm(base,p-2);
            for(int len=mid<<1,i=0;i<limit;i+=len)
            {
                int w=1;
                for(int j=0;j<mid;j++,w=(ll)w*base%p)
                {
                    int x=nw[i+j];    int y=(ll)w*nw[i+j+mid]%p;
                    nw[i+j]=(x+y)%p;    nw[i+j+mid]=(x-y+p)%p;
                }
            }
        }
    }
    void mul(int *A,int *B,int *C,int len)
    {
        for(int i=len+1;i<limit;++i)    A[i]=B[i]=0;
        NTT(A,1);    NTT(B,1);
        for(int i=0;i<limit;++i)    C[i]=(ll)A[i]*B[i]%p;
        NTT(C,-1);    int INV=ksm(limit,p-2);
        for(int i=0;i<limit;++i)    C[i]=(ll)C[i]*INV%p;
    }
    void solve(int LEN)
    {
        if(LEN<=1)    {    ans[LEN]=1;    return ;}
        solve(LEN>>1);    int len=LEN>>1;    fir(len);
        for(int i=1;i<=len;++i)    tmp[i]=(ll)tmp[i-1]*len%p;
        for(int i=0;i<=len;++i)    a[i]=(ll)tmp[i]*fav[i]%p;
        for(int i=0;i<=len;++i)    b[i]=(ll)ans[i]*fac[i]%p;
        for(int i=0;i<=(len>>1);++i)    swap(b[i],b[len-i]);
        mul(a,b,c,len);
        for(int i=0;i<=len;++i)    a[i]=(ll)c[len-i]*fav[i]%p;
        for(int i=0;i<=len;++i)    b[i]=ans[i];
        mul(a,b,c,len);
        for(int i=0;i<=LEN;++i)    ans[i]=c[i];
        if(LEN&1)
            for(int i=1;i<=LEN;++i)
                ans[i]=((ll)c[i]*(LEN-1)%p+c[i-1])%p;
    }
    int main()
    {
        scanf("%d",&n);
        fac[0]=fac[1]=fav[0]=fav[1]=tmp[0]=1;
        for(int i=1;i<=n;++i)    fac[i]=(ll)fac[i-1]*i%p;
        for(int i=2;i<=n;++i)    fav[i]=p-(ll)p/i*fav[p%i]%p;
        for(int i=1;i<=n;++i)    fav[i]=(ll)fav[i-1]*fav[i]%p;
        solve(n);
        for(int i=0;i<=n;++i)    printf("%d ",ans[i]);
        return 0;
    }
    View Code

        第二类斯特林数(行):

    #include<bits/stdc++.h>
    #define ll long long
    #define p 167772161
    using namespace std;
    int n,limit,s;
    int fac[1000050];
    int fav[1000050];
    int pos[1000050];
    int ans[1000050];
    int a[1000050];
    int b[1000050];
    int ksm(int u,int v)
    {
        int sum=1;
        while(v)
        {
            if(v&1)    sum=(ll)sum*u%p;
            v>>=1;    u=(ll)u*u%p;
        }
        return sum;
    }
    void calc(int len)
    {
        limit=1;    s=0;
        while(limit<=(len<<1))    limit<<=1,s++;
        for(int i=0;i<limit;++i)    pos[i]=(pos[i>>1]>>1)|((i&1)<<(s-1));
    }
    void NTT(int *nw,int opt)
    {
        for(int i=0;i<limit;++i)
            if(i<pos[i])    swap(nw[i],nw[pos[i]]);
        for(int mid=1;mid<limit;mid<<=1)
        {
            int base=ksm(3,(p-1)/(mid<<1));
            if(opt==-1)    base=ksm(base,p-2);
            for(int len=mid<<1,i=0;i<limit;i+=len)
            {
                int w=1;
                for(int j=0;j<mid;j++,w=(ll)w*base%p)
                {
                    int x=nw[i+j];    int y=(ll)w*nw[i+j+mid]%p;
                    nw[i+j]=(x+y)%p;    nw[i+j+mid]=(x-y+p)%p;
                }
            }
        }
    }
    void mul(int *A,int *B,int *C,int len)
    {
        for(int i=len+1;i<limit;++i)    A[i]=B[i]=0;
        NTT(A,1);    NTT(B,1);
        for(int i=0;i<limit;++i)    C[i]=(ll)A[i]*B[i]%p;
        NTT(C,-1);    int INV=ksm(limit,p-2);
        for(int i=0;i<limit;++i)    C[i]=(ll)C[i]*INV%p;
    }
    int main()
    {
        scanf("%d",&n);
        fac[0]=fac[1]=fav[0]=fav[1]=1;
        for(int i=1;i<=n;++i)    fac[i]=(ll)fac[i-1]*i%p;
        for(int i=2;i<=n;++i)    fav[i]=p-(ll)p/i*fav[p%i]%p;
        for(int i=1;i<=n;++i)    fav[i]=(ll)fav[i-1]*fav[i]%p;
        for(int i=0;i<=n;++i)    a[i]=(i&1)?    -fav[i]:fav[i];
        for(int i=0;i<=n;++i)    b[i]=(ll)ksm(i,n)*fav[i]%p;
        calc(n);    mul(a,b,ans,n);
        for(int i=0;i<=n;++i)    printf("%d ",ans[i]);
        return 0;
    }
    View Code

     网络流:

      求解一组最小割边:

    #include<bits/stdc++.h>
    #define INF 1<<30
    using namespace std;
    int read()
    {
        int x=0,f=1;    char ch=getchar();
        while(ch<'0'||ch>'9')    {if(ch=='-')    f=-1;    ch=getchar();}
        while(ch>='0'&&ch<='9')    {x=(x<<3)+(x<<1)+(ch^48);    ch=getchar();}
        return x*f;
    }
    queue<int >q;
    int dis[100050];
    bool vis[100050]; 
    int n,m,s,t,tot=1,x,y,z,ans;
    int head[100050],nex[100050],ver[100050],flow[100050];
    void add(int x,int y,int z)
    {
        ++tot;nex[tot]=head[x];head[x]=tot;ver[tot]=y;flow[tot]=z;
        ++tot;nex[tot]=head[y];head[y]=tot;ver[tot]=x;flow[tot]=0;
    }
    bool bfs()
    {
        memset(dis,0,sizeof(dis));
        q.push(s);    dis[s]=1;
        while(!q.empty())
        {
            int u=q.front();    q.pop();
            for(int i=head[u];i;i=nex[i])
            {
                int v=ver[i];
                if(!dis[v]&&flow[i])
                {
                    dis[v]=dis[u]+1;
                    if(v!=t)    q.push(v);
                }
            }
        }
        return dis[t];
    }
    int dfs(int u,int FLOW)
    {
        if(u==t)    return FLOW;
        int VAL=0;
        for(int i=head[u];i;i=nex[i])
        {
            int v=ver[i];
            if(dis[v]==dis[u]+1&&flow[i])
            {
                int tmp=dfs(v,min(FLOW,flow[i]));
                flow[i]-=tmp;    flow[i^1]+=tmp;
                VAL+=tmp;    FLOW-=tmp;
                if(!tmp)    dis[v]=0;
                if(!FLOW)    break;
            }
        }
        return VAL;
    }
    void calc()
    {
        q.push(s);    vis[s]=true;
        while(!q.empty())
        {
            int u=q.front();    q.pop();
            for(int i=head[u];i;i=nex[i])
            {
                int v=ver[i];
                if(!flow[i])    continue;
                if(!vis[v])
                {
                    q.push(v);
                    vis[v]=true;
                }
            }
        }
    }
    int main()
    {
        n=read();    m=read();    s=read();    t=read()+n;
        for(int i=1;i<=n;++i)    add(i,i+n,read());
        for(int i=1;i<=m;++i)
        {
            x=read();    y=read();
            add(x+n,y,INF);    add(y+n,x,INF);
        }
        while(bfs())    ans+=dfs(s,INF);
        calc();
        for(int i=1;i<=n;++i)
            if(vis[i]&&!vis[i+n])    printf("%d ",i);
        return 0;
    }
    View Code

        求解可行边与必须边:

    #include<bits/stdc++.h>
    using namespace std;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9')    {if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9')    x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
        return x*f;
    }
    int n,m,x,y,z,S,T;
    int dfn[10050],low[10050],t[10050],top,cnt,col[10050],sum;
    int head[10050],nex[120050],ver[120050],flow[120050],tot=1;
    int dis[10050]; queue<int >q;
    bool bfs()
    {
        memset(dis,0,sizeof(dis));
        q.push(S);    dis[S]=1;
        while(!q.empty())
        {
            int u=q.front();    q.pop();
            for(int i=head[u];i;i=nex[i])
            {
                int v=ver[i];
                if(!dis[v]&&flow[i])
                {
                    dis[v]=dis[u]+1;
                    if(v!=T)    q.push(v);
                }
            }
        }
        return dis[T];
    }
    int dfs(int u,int FLOW)
    {
        if(u==T)    return FLOW;
        int VAL=0;
        for(int i=head[u];i;i=nex[i])
        {
            int v=ver[i];
            if(dis[v]==dis[u]+1&&flow[i])
            {
                int tmp=dfs(v,min(FLOW,flow[i]));
                if(!tmp)    dis[v]=0;
                flow[i]-=tmp;    flow[i^1]+=tmp;
                VAL+=tmp;    FLOW-=tmp;
                if(!FLOW)    break;
            }
        }
        return VAL;
    }
    void tarjan(int u)
    {
        dfn[u]=low[u]=++cnt;    t[++top]=u;
        for(int i=head[u];i;i=nex[i])
        {
            if(!flow[i])    continue;
            int v=ver[i];
            if(!dfn[v])
            {
                tarjan(v);
                low[u]=min(low[u],low[v]);
            }
            else if(!col[v])
                low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u])
        {
            ++sum;
            while(t[top+1]!=u)
                col[t[top--]]=sum;
        }
    }
    int main()
    {
        n=read();    m=read();    S=read();    T=read();
        for(int i=1;i<=m;++i)
        {
            x=read();    y=read();    z=read();
            ++tot;nex[tot]=head[x];head[x]=tot;ver[tot]=y;flow[tot]=z;
            ++tot;nex[tot]=head[y];head[y]=tot;ver[tot]=x;flow[tot]=0;
        }
        while(bfs())    dfs(S,1<<30);
        for(int i=1;i<=n;++i)    if(!dfn[i])    tarjan(i);
        for(int i=2;i<=tot;i+=2)
            if(!flow[i])
            {
                if(col[ver[i]]!=col[ver[i^1]])    printf("1 ");
                else    printf("0 ");
                if(col[S]==col[ver[i^1]]&&col[ver[i]]==col[T])    printf("1
    ");
                else    printf("0
    ");
            }
            else
                printf("0 0
    ");
        return 0;
    }
    View Code

     

  • 相关阅读:
    hadoop测试题目每天5题,总35题,第一天
    hadoop测试题目每天5题,总35题,第四天
    hadoop测试题目每天5题,总35题,第五天
    SP_EXECUTESQL 的用法
    元数据函数的使用 快速定位数据相关过程,表,函数
    javascript 層的拖動
    如何求得一个月的最后一个工作日
    利用ASP.NET实现分页管理器(高级篇)轉
    Asp.Net页面输出到EXCEL
    .net相关专题汇总
  • 原文地址:https://www.cnblogs.com/wyher/p/10880285.html
Copyright © 2011-2022 走看看