多项式

一、多项式求导

$F'(x)=\sum_{i=0}a_{i+1}\times (i+1)x $

点击查看代码
inline void dao(int *g,int *f){
    for(int i=0;i<n;++i)  g[i]=f[i+1]*(i+1)%mod;
}

二、多项式求积分

求导逆运算

$F'(x)=\sum_{i=1}a_{i-1}\times \frac{1}{i}x $

点击查看代码
inline void jifen(int *g,int *f){
    for(int i=1;i<=n;++i)  g[i]=f[i-1]*power(i,mod-2)%mod;
}

三、多项式求逆

不取模

点击查看代码
void ni(int len){
    if(len==1){g[0]=power(f[0],mod-2);return;}
    solve(len>>1);work(len);
	for(int i=0;i<len;i++) a[i]=f[i],b[i]=g[i];
	for(int i=len;i<bl;i++) a[i]=b[i]=0; NTT(a,bl,1);NTT(b,bl,1);
	for(int i=0;i<bl;i++) a[i]=1ll*a[i]*b[i]%mod*b[i]%mod; NTT(a,bl,-1);
	for(int i=0;i<len;i++) g[i]=((2ll*g[i]%mod-a[i])%mod+mod)%mod;
}

四、多项式求ln

求导后积分

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAX=6e5+10;
#define int long long
const int mod=998244353,G=3;
int n,m=1,bl,bc,rev[MAX],a[MAX],b[MAX],f[MAX],g[MAX],g2[MAX];
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^'0');c=getchar();}
	return x*f;
}
inline int power(int a,int b){
    int res=1;
    while(b){
        if(b&1)  res=res*a%mod;
        a=a*a%mod;b>>=1;
    }return res;
}inline void NTT(int*,int,int);
void solve(int);
inline void work(int len){
    bl=1;bc=0;
    while(bl<=len)  bl<<=1,++bc;
    for(int i=0;i<bl;++i)
        rev[i]=(rev[i>>1]>>1)|((i&1)<<bc-1);
}
inline void dao(int *g,int *f){
    for(int i=0;i<n;++i)  g[i]=f[i+1]*(i+1)%mod;
}inline void jifen(int *g,int n){
    for(int i=n;i;--i)  g[i]=g[i-1]*power(i,mod-2)%mod;
    g[0]=0;
}
signed main(){ 
    n=read();
    for(int i=0;i<n;++i)  f[i]=read();
    while(m<=n)  m<<=1;
    solve(m);work(n<<1);dao(g2,f);
    //g=invf  g2=f'
    NTT(g,bl,1);NTT(g2,bl,1);
    for(int i=0;i<bl;++i)  g[i]=g[i]*g2[i]%mod;
    NTT(g,bl,-1);
    //g=lnf'
    jifen(g,bl);
    for(int i=0;i<n;++i)  printf("%lld ",g[i]);
}
void solve(int len){
    if(len==1){g[0]=power(f[0],mod-2);return;}
    solve(len>>1);work(len);
	for(int i=0;i<len;i++) a[i]=f[i],b[i]=g[i];
	for(int i=len;i<bl;i++) a[i]=b[i]=0; NTT(a,bl,1);NTT(b,bl,1);
	for(int i=0;i<bl;i++) a[i]=1ll*a[i]*b[i]%mod*b[i]%mod; NTT(a,bl,-1);
	for(int i=0;i<len;i++) g[i]=((2ll*g[i]%mod-a[i])%mod+mod)%mod;
}inline void NTT(int *a,int n,int op){
    for(int i=0;i<n;++i)
        if(i<rev[i])  swap(a[i],a[rev[i]]);
    for(int i=1;i<n;i<<=1){
        int wn=power(G,(op*(mod-1)/(i<<1)+mod-1)%(mod-1));
        for(int j=0;j<n;j+=i<<1){
            int w=1;
            for(int k=0;k<i;++k){
                int x=a[j+k],y=a[j+k+i]*w%mod;
                a[j+k]=(x+y)%mod;a[j+k+i]=(x-y+mod)%mod;
                w=w*wn%mod;
            }
        }
    }if(op==-1){
        int inv=power(n,mod-2);
        for(int i=0;i<n;++i)  a[i]=a[i]*inv%mod;
    }
}

五、MTT

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAX=4e5+10;
#define int long long
const long double pi=M_PI;
struct com{
    long double r,i;
} A[MAX],B[MAX],C[MAX],D[MAX];
inline com operator+(const com &a,const com &b){
    return{a.r+b.r,a.i+b.i};
}inline com operator-(const com &a,const com &b){
    return {a.r-b.r,a.i-b.i};
}inline com operator*(const com &a,const com &b){
    return {a.r*b.r-a.i*b.i,a.r*b.i+a.i*b.r};
}
int n,m,bl=1,bc,rev[MAX],mod;
int a[MAX],b[MAX],c[MAX],inv;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^'0');c=getchar();}
	return x*f;
}
inline void MUL(int*,int*,int);
signed main(){ 
    n=read();m=read();mod=read();
    for(int i=0;i<=n;++i)  a[i]=read();
    for(int i=0;i<=m;++i)  b[i]=read();
    int len=n+m;
    while(bl<=len)  ++bc,bl<<=1;
    for(int i=0;i<bl;++i)
        rev[i]=(rev[i>>1]>>1)|((i&1)<<(bc-1));
    MUL(a,b,bl);
    for(int i=0;i<=len;++i)
        printf("%lld ",a[i]);
}
void FFT(com *a,int n,int op){
    for(int i=0;i<n;++i)
        if(i<rev[i])  swap(a[i],a[rev[i]]);
    for(int i=1;i<n;i<<=1){
        com wn={cos(pi/i),op*sin(pi/i)};
        int st=i<<1;
        for(int j=0;j<n;j+=st){
            com w=com{1,0};
            for(int k=0;k<i;++k,w=w*wn){
                com x=a[j+k],y=w*a[j+k+i];
                a[j+k]=x+y;a[j+k+i]=x-y;
            }
        }
    }if(op==-1)
        for(int i=0;i<n;++i)  a[i].r/=n;
    
}inline void MUL(int *a,int *b,int n){
    for(int i=0;i<n;++i){
        a[i]%=mod;b[i]%=mod;
        A[i]={(a[i]>>15)*1.0,0};B[i]={(a[i]&32767)*1.0,0};
        C[i]={(b[i]>>15)*1.0,0};D[i]={(b[i]&32767)*1.0,0};
    }FFT(A,n,1);FFT(B,n,1);FFT(C,n,1);FFT(D,n,1);
    for(int i=0;i<n;++i){
        com aa=A[i]*C[i],bb=A[i]*D[i]+B[i]*C[i],cc=B[i]*D[i];
        A[i]=aa;B[i]=bb;C[i]=cc;
    }FFT(A,n,-1);FFT(B,n,-1);FFT(C,n,-1);
    int t=(1ll<<15)%mod;
    for(int i=0;i<n;++i){
        a[i]=((llround(A[i].r)%mod)*(t*t%mod))%mod+((llround(B[i].r)%mod)*t)%mod+llround(C[i].r)%mod;
        a[i]%=mod;
    }
}

六、exp

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAX=4e5+10;
#define int long long
const int mod=998244353;
int n,m=1,bl,bc,a[MAX],b[MAX],rev[MAX],c[MAX],d[MAX],A[MAX],B[MAX],g2[MAX];
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^'0');c=getchar();}
	return x;
}
inline int power(int a,int b){
    int res=1;
    while(b){
        if(b&1)  res=res*a%mod;
        a=a*a%mod;b>>=1;
    }return res;
}inline void NTT(int*,int,int);
void solve(int*,int*,int);
inline void dao(int *g,int *f,int n){
    for(int i=0;i<n;++i)  g[i]=f[i+1]*(i+1)%mod;g[n-1]=0;
}inline void jifen(int *g,int n){
    for(int i=n;i;--i)  g[i]=g[i-1]*power(i,mod-2)%mod;
    g[0]=0;
}inline void mul(int*,int*,int*,int);
inline void ln(int *f,int *g,int n){
    int m=1;
    while(m<=n)  m<<=1;
    for(int i=0;i<m;++i)  g[i]=0;//
    solve(f,g,m);dao(g2,f,n);
    mul(g,g2,g,n);
    jifen(g,n);
}void exp(int *a,int *b,int n){
    if(n==1){b[0]=1;return;}
    exp(a,b,n+1>>1);
    ln(b,c,n);
    for(int i=0;i<n;++i)  d[i]=(a[i]-c[i]+mod)%mod;
    d[0]++;
    mul(b,d,b,n);
    for(int i=n;i<bl;++i)  b[i]=0;
}
signed main(){ 
    // freopen("1.txt","r",stdin);
	n=read();
	for(int i=0;i<n;++i)  a[i]=read();
    exp(a,b,n);
	for(int i=0;i<n;++i)  printf("%lld ",b[i]);
}
void solve(int *f,int *g,int len){
    if(len==1){g[0]=power(f[0],mod-2);return;}
    solve(f,g,len>>1);
    bl=1;bc=0;
    while(bl<=len)  bl<<=1,++bc;
    for(int i=0;i<bl;++i)
        rev[i]=(rev[i>>1]>>1)|((i&1)<<bc-1);
	for(int i=0;i<len;i++) A[i]=f[i],B[i]=g[i];
	for(int i=len;i<bl;i++) A[i]=B[i]=0; NTT(A,bl,1);NTT(B,bl,1);
	for(int i=0;i<bl;i++) A[i]=1ll*A[i]*B[i]%mod*B[i]%mod; NTT(A,bl,-1);
	for(int i=0;i<len;i++) g[i]=((2ll*g[i]%mod-A[i])%mod+mod)%mod;
}inline void NTT(int *a,int n,int op){
    for(int i=0;i<n;++i)
        if(i<rev[i])  swap(a[i],a[rev[i]]);
    for(int i=1;i<n;i<<=1){
        int wn=power(3,(op*(mod-1)/(i<<1)+mod-1)%(mod-1));
        for(int j=0;j<n;j+=i<<1){
            int w=1;
            for(int k=0;k<i;++k){
                int x=a[j+k],y=a[j+k+i]*w%mod;
                a[j+k]=(x+y)%mod;a[j+k+i]=(x-y+mod)%mod;
                w=w*wn%mod;
            }
        }
    }if(op==-1){
        int inv=power(n,mod-2);
        for(int i=0;i<n;++i)  a[i]=a[i]*inv%mod;
    }
}inline void mul(int *a,int *b,int *c,int n){
    bl=1;bc=0;
    while(bl<=n<<1)  bl<<=1,++bc;
    for(int i=0;i<bl;++i)
        rev[i]=(rev[i>>1]>>1)|((i&1)<<bc-1);
    for(int i=0;i<n;++i)  A[i]=a[i],B[i]=b[i];
    for(int i=n;i<bl;++i)  A[i]=B[i]=0;
    NTT(A,bl,1);NTT(B,bl,1);
    for(int i=0;i<bl;++i)  c[i]=A[i]*B[i]%mod;
    NTT(c,bl,-1);
}


七、分治FFT

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAX=2e5+10;
const int mod=998244353;
#define int long long
int n,f[MAX],g[MAX],bl,bc,rev[MAX];
int a[MAX],b[MAX],inv;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^'0');c=getchar();}
	return x*f;
}
inline void NTT(int*,int,int);
inline int power(int a,int b){
    int res=1;
    while(b){
        if(b&1)  res=res*a%mod;
        a=a*a%mod;b>>=1;
    }return res;
}void solve(int,int);
inline void work(int len){
    bl=1;bc=0;
    while(bl<=len)  bl<<=1,++bc;
    for(int i=0;i<bl;++i)
        rev[i]=(rev[i>>1]>>1)|((i&1)<<bc-1);
}
signed main(){ 
    n=read();
    for(int i=1;i<n;++i)  g[i]=read();
    solve(0,n-1);f[0]=1;
    for(int i=0;i<n;++i)  printf("%lld ",f[i]);

}
inline void NTT(int *a,int n,int op){
    for(int i=0;i<n;++i)  
        if(i<rev[i])  swap(a[i],a[rev[i]]);
    for(int i=1;i<n;i<<=1){
        int wn=power(3,(op*(mod-1)/(i<<1)+mod-1)%(mod-1));
        for(int j=0;j<n;j+=i<<1){
            int w=1;
            for(int k=0;k<i;++k){
                int x=a[j+k],y=w*a[j+k+i]%mod;
                a[j+k]=(x+y)%mod;a[j+k+i]=(x-y+mod)%mod;
                w=w*wn%mod;
            }
        }
    }if(op==-1){
        inv=power(n,mod-2);
        for(int i=0;i<n;++i)  a[i]=a[i]*inv%mod;
    } 
}void solve(int l,int r){
    // cout<<l<<" "<<r<<endl;
    if(l==r){f[l]=(f[l]+g[l])%mod;return;}
    int mid=l+r>>1;
    solve(l,mid);work(r-l+1);
    for(int i=0;i<bl;++i)  a[i]=b[i]=0;
    for(int i=l;i<=mid;++i)  a[i-l]=f[i];
    for(int i=0;i<=r-l;++i)  b[i]=g[i];
    NTT(a,bl,1);NTT(b,bl,1);
    for(int i=0;i<bl;++i)  a[i]=a[i]*b[i]%mod;
    NTT(a,bl,-1);
    for(int i=mid+1;i<=r;++i)  f[i]=(f[i]+a[i-l])%mod;
    solve(mid+1,r);
}

八、多项式除法

题面

找到一种变换R使得\(A_R(x)=x^n A(\frac{1}{x})\),可以发现\(A_R[i]=A[n-i]\),即系数翻转

\[\begin{aligned}F(x)&=Q(x)G(x)+R(x)\\ F(\frac{1}{x})&=Q(\frac{1}{x})G(\frac{1}{x})+R(\frac{1}{x})\\ x^n F(\frac{1}{x})&=x^{n-m}Q(\frac{1}{x}) \times x^m G(\frac{1}{x})+x^{n-m+1} \times x^{m-1} R(\frac{1}{x})\\ F_R(x)&=Q_R(x)G_R(x)+x^{n-m+1}R_R(x)\\ F_R(x)&\equiv Q_R(x)G_R(x) \pmod {x^{n-m+1}}\\ Q_R(x)&\equiv F_R(x)G_R(x)^{-1}\pmod {x^{n-m+1}}\\ R(x)&=F(x)-G(x)Q(x) \end{aligned}\]

点击查看代码
#include<bits/stdc++.h>
using namespace std;
const int MAX=3e5+10;
#define int long long
const int mod=998244353;
int n,m,f[MAX],g[MAX],bl,bc,rev[MAX],q[MAX],r[MAX],iG[MAX];
int a[MAX],b[MAX],inv,A[MAX],B[MAX];
inline int read(){
	int x=0,f=1;char c=getchar();
	while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
	while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^'0');c=getchar();}
	return x*f;
}
inline void chu(int*,int*,int*,int*,int,int);
signed 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();
    chu(f,g,q,r,n,m);
    for(int i=0;i<=n-m;++i)  printf("%lld ",q[i]);
    printf("\n");
    for(int i=0;i<m;++i)  printf("%lld ",r[i]);
}
inline int power(int a,int b){
    int res=1;
    while(b){
        if(b&1)  res=res*a%mod;
        a=a*a%mod;b>>=1;
    }return res;
}inline void work(int n){
    bl=1;bc=0;
    while(bl<=n)  bl<<=1,++bc;
    for(int i=0;i<bl;++i)
        rev[i]=(rev[i>>1]>>1)|((i&1)<<bc-1);
}inline void NTT(int *a,int n,int op){
    for(int i=0;i<n;++i)  
        if(i<rev[i])  swap(a[i],a[rev[i]]);
    for(int i=1;i<n;i<<=1){
        int wn=power(3,(op*(mod-1)/(i<<1)+mod-1)%(mod-1));
        for(int j=0;j<n;j+=i<<1){
            int w=1;
            for(int k=0;k<i;++k){
                int x=a[j+k],y=w*a[j+k+i]%mod;
                a[j+k]=(x+y)%mod;a[j+k+i]=(x-y+mod)%mod;
                w=w*wn%mod;
            }
        }
    }if(op==-1){
        inv=power(n,mod-2);
        for(int i=0;i<n;++i)  a[i]=a[i]*inv%mod;
    } 
}inline void mul(int *f,int *g,int *c,int n){
    work(n);
    for(int i=0;i<n;++i)  a[i]=f[i],b[i]=g[i];
    for(int i=n;i<bl;++i)  a[i]=b[i]=0;
    NTT(a,bl,1);NTT(b,bl,1);
    for(int i=0;i<bl;++i)  a[i]=a[i]*b[i]%mod;
    NTT(a,bl,-1);
    for(int i=0;i<n;++i)  c[i]=a[i];
}void solve(int *f,int *g,int n){
    if(n==1){g[0]=power(f[0],mod-2);return;}
    solve(f,g,n>>1);work(n);
    for(int i=0;i<n;++i)  a[i]=f[i],b[i]=g[i];
    for(int i=n;i<bl;++i)  a[i]=b[i]=0;NTT(a,bl,1);NTT(b,bl,1);
    for(int i=0;i<bl;++i)  a[i]=a[i]*b[i]%mod*b[i]%mod;NTT(a,bl,-1);
    for(int i=0;i<n;++i)  g[i]=(2*g[i]-a[i]+mod)%mod;
}
inline void chu(int *f,int *g,int *q,int *r,int n,int m){
    for(int i=0;i<=n;++i)  A[i]=f[n-i];
    for(int i=0;i<=min(m,n-m);++i)  B[i]=g[m-i];
    int M=1;while(M<=n-m+1)  M<<=1;
    solve(B,iG,M);
    mul(A,iG,q,n+1+M);
    for(int i=n-m+1;i<bl;++i)  q[i]=0;
    reverse(q,q+n-m+1);
    mul(g,q,r,m+n-m+2);
    for(int i=0;i<m;++i)  r[i]=(f[i]-r[i]+mod)%mod;
}

九、多点求值

一个推荐

posted @ 2024-01-29 18:08  yisiwunian  阅读(24)  评论(1编辑  收藏  举报