多项式全家桶

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

 

咕了

posted @ 2019-06-05 10:22  hfctf0210  阅读(172)  评论(0编辑  收藏  举报