Luogu P4726 【模板】多项式指数函数(多项式 exp)

多项式全家桶

运算法则 算法 时间复杂度
多项式乘法 快速傅里叶变换 Θ ( n log ⁡ 2 n ) \Theta(n\log_2 n) Θ(nlog2n)
多项式求逆 倍增+快速数论变换 Θ ( n log ⁡ 2 n ) \Theta(n\log_2 n) Θ(nlog2n)
多项式对数函数 求导+积分 Θ ( n log ⁡ 2 n ) \Theta(n\log_2 n) Θ(nlog2n)
多项式指数函数 泰勒展开+牛顿迭代 Θ ( n log ⁡ 2 n ) \Theta(n\log_2 n) Θ(nlog2n)
分治FFT卷积 分治FFT/多项式求逆 Θ ( n log ⁡ 2 2 n ) / Θ ( n log ⁡ 2 n ) \Theta(n\log_2^2 n)/\Theta(n\log_2 n) Θ(nlog22n)/Θ(nlog2n)

题目大意

%   给出 n − 1 n-1 n1 次多项式 A ( x ) A(x) A(x),求一个模 x n x^n xn 意义下的多项式 B ( x ) B(x) B(x),满足 B ( x ) ≡ e A ( x ) B(x) \equiv e^{A(x)} B(x)eA(x)
  数据范围  1 ⩽ 1 0 5 1\leqslant 10^5 1105,多项式的常数项为0。

题解

%   从牛顿迭代讲起吧,泰勒展开可以去看3b1b的视频。

%   已知多项式函数 G ( x ) G(x) G(x),求多项式函数 F ( x ) F(x) F(x),满足
G ( F ( x ) ) ≡ 0 ( m o d x n ) (1) G(F(x))\equiv 0\pmod {x^n}\tag{1} G(F(x))0(modxn)(1)  假设我们已经求出了 F 0 ( x ) F_0(x) F0(x) 满足
G ( F 0 ( x ) ) ≡ 0 ( m o d x ⌈ n 2 ⌉ ) G(F_0(x))\equiv0\pmod {x^{\small\lceil\frac{n}{2}\rceil}} G(F0(x))0(modx2n)  则函数 G ( x ) G(x) G(x) x = F 0 ( x ) x=F_0(x) x=F0(x) 处的泰勒展开式为
G ( F ( x ) ) ≡ ∑ i = 1 ∞ G i ( F 0 ( x ) ) i ! ( F ( x ) − F 0 ( x ) ) i ( m o d x n ) (2) G(F(x))\equiv\sum_{i=1}^{\infty}\frac{G^i(F_0(x))}{i!}\left(F(x)-F_0(x)\right)^i\pmod{x^n}\tag{2} G(F(x))i=1i!Gi(F0(x))(F(x)F0(x))i(modxn)(2)  其中 G i G^i Gi G G G i i i 阶导函数。由于 F ( x ) F(x) F(x) F 0 ( x ) F_0(x) F0(x) 的 0 次项到 ⌈ n 2 ⌉ \lceil\frac n2\rceil 2n 次项均相同,因而有
F ( x ) − F 0 ( x ) ≡ 0 ( m o d x ⌈ n 2 ⌉ ) F(x)-F_0(x)\equiv0\pmod {x^{\small\left\lceil\frac n2\right\rceil}} F(x)F0(x)0(modx2n)  两边平方
( F ( x ) − F 0 ( x ) ) 2 ≡ 0 ( m o d x n ) (F(x)-F_0(x))^2\equiv0\pmod {x^n} (F(x)F0(x))20(modxn)  因而对于任意 i ⩾ 2 i\geqslant2 i2,有
( F ( x ) − F 0 ( x ) ) i ≡ 0 ( m o d x n ) (F(x)-F_0(x))^i\equiv0\pmod {x^n} (F(x)F0(x))i0(modxn)  因而对于 ( 2 ) (2) (2) 式, i ⩾ 2 i\geqslant2 i2 的项均为0,因而有
G ( F ( x ) ) ≡ G ( F 0 ( x ) ) + G ′ ( F 0 ( x ) ) ( F ( x ) − F 0 ( x ) ) ( m o d x n ) G(F(x))\equiv G(F_0(x))+G'(F_0(x))(F(x)-F_0(x))\pmod {x^n} G(F(x))G(F0(x))+G(F0(x))(F(x)F0(x))(modxn)  将 ( 1 ) (1) (1) 式代入,得
G ( F 0 ( x ) ) + G ′ ( F 0 ( x ) ) ( F ( x ) − F 0 ( x ) ) ≡ 0 ( m o d x n ) G(F_0(x))+G'(F_0(x))(F(x)-F_0(x))\equiv 0 \pmod {x^n} G(F0(x))+G(F0(x))(F(x)F0(x))0(modxn)  移项整理,得
F ( x ) ≡ F 0 ( x ) − G ( F 0 ( x ) ) G ′ ( F 0 ( x ) ) ( m o d x n ) (3) F(x)\equiv F_0(x)-\frac{G(F_0(x))}{G'(F_0(x))} \pmod {x^n}\tag{3} F(x)F0(x)G(F0(x))G(F0(x))(modxn)(3)

%   回到题目,考虑
B ( x ) ≡ e A ( x ) ( m o d x n ) B(x)\equiv e^{A(x)}\pmod {x^{n}} B(x)eA(x)(modxn)  移项两边取对数
ln ⁡ B ( x ) − A ( x ) ≡ 0 ( m o d x n ) \ln B(x)-A(x)\equiv0\pmod{x^n} lnB(x)A(x)0(modxn)  令 G ( B ( x ) ) ≡ ln ⁡ B ( x ) − A ( x ) ( m o d x n ) G(B(x))\equiv\ln B(x)-A(x)\pmod{x^n} G(B(x))lnB(x)A(x)(modxn)  其中 B ( x ) B(x) B(x) 为自变量,因而 A ( x ) A(x) A(x) 为常数,两边求导,得
G ′ ( B ( x ) ) ≡ B − 1 ( x ) ( m o d x n ) G'(B(x))\equiv B^{-1}(x)\pmod{x^n} G(B(x))B1(x)(modxn)  令 F ( x ) = B ( x ) F(x)=B(x) F(x)=B(x),代入 ( 3 ) (3) (3) 式,得
B ( x ) ≡ B 0 ( x ) − G ( B 0 ( x ) ) B 0 − 1 ( x ) ≡ B 0 ( x ) − B 0 ( x )   G ( B 0 ( x ) ) ≡ B 0 ( x ) − B 0 ( x ) ln ⁡ B 0 ( x ) + B 0 ( x ) A ( x ) ≡ B 0 ( x ) ( 1 − ln ⁡ B 0 ( x ) + A ( x ) ) ( m o d x n ) \begin{aligned}B(x)&\equiv B_0(x)-\frac{G(B_0(x))}{B_0^{-1}(x)}\\ &\equiv B_0(x)-B_0(x)\,G(B_0(x))\\ &\equiv B_0(x)-B_0(x)\ln B_0(x)+B_0(x)A(x)\\ &\equiv B_0(x)\left(1-\ln B_0(x)+A(x)\right) \pmod{x^n} \end{aligned} B(x)B0(x)B01(x)G(B0(x))B0(x)B0(x)G(B0(x))B0(x)B0(x)lnB0(x)+B0(x)A(x)B0(x)(1lnB0(x)+A(x))(modxn)  因为 A ( 0 ) = 0 A(0)=0 A(0)=0,从而 B ( 0 ) = 1 B(0)=1 B(0)=1,因而可以倍增地求解,总时间复杂度为 T ( n ) = T ( n 2 ) + Θ ( n log ⁡ 2 n ) (4) T(n)=T\left(\frac n2\right)+\Theta(n\log_2n)\tag{4} T(n)=T(2n)+Θ(nlog2n)(4)  根据主定理,可得程序的时间复杂度为1 T ( n ) = Θ ( n log ⁡ 2 n ) T(n)=\Theta(n\log_2n) T(n)=Θ(nlog2n)

// luogu-judger-enable-o2
#include
using namespace std;
#define ll long long
#define maxn 400010
const ll mod=(119<<23)+1,G=3,inv_G=332748118;
ll pow_t(ll a,ll b){
    ll ret=1;
    for(a%=mod;b;a=a*a%mod,b>>=1)
        if(b&1) ret=ret*a%mod;
    return ret;
} ll inv(ll x){return pow_t(x,mod-2);}
struct poly{
    private:ll q_lens;
    public:ll *t;
    poly(int n=maxn):q_lens(n+10){
    	t=(ll*)malloc((n+10)*sizeof (ll));
    	memset(t,0,(n+10)*sizeof (ll));
    } ~poly(){free(t);}
    void sets(){memset(t,0,q_lens*sizeof (ll));}
    ll &operator[](const int &x){return t[x];}
    const ll &operator[](const int &x)const{return t[x];}
};
int limit,l,r[maxn];
void calc(int n,int m){
    for(limit=1,l=0;limit<=n+m;limit<<=1,++l);
    for(int i=0;i<limit;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(l-1));
}
void NTT(poly &t,bool un=false){
    for(int i=0;i<limit;i++)
        if(i<r[i]) swap(t[i],t[r[i]]);
    for(int mid=1;mid<limit;mid<<=1){
        ll wn=pow_t((un?inv_G:G),(mod-1)/(mid<<1));
        for(int j=0;j<limit;j+=(mid<<1)){
            ll w=1;
            for(int k=0;k<mid;++k,w=w*wn%mod){
                ll x=t[j+k],y=w*t[j+k+mid]%mod;
                t[j+k]=(x+y)%mod;
                t[j+k+mid]=(x-y+mod)%mod;
            }
        }
    } ll invs=inv(limit);
    if(un) for(int i=0;i<limit;i++)
        t[i]=t[i]*invs%mod;
}
void inv(int n,const poly &f,poly &g){
    if(n==1) return(void)(g[0]=inv(f[0]));
    inv((n+1)>>1,f,g); calc(n,n);
    poly a(limit),b(limit);
    for(int i=0;i<n;i++) a[i]=f[i],b[i]=g[i];
    NTT(a); NTT(b);
    for(int i=0;i<limit;i++)
        b[i]=b[i]*((2ll-a[i]*b[i]%mod+mod)%mod)%mod;
    NTT(b,true);
    for(int i=0;i<n;i++) g[i]=b[i]%mod;
}
void dao(int n,const poly &A,poly &B){
    for(int i=1;i<n;i++)
        B[i-1]=1ll*i*A[i]%mod;
    B[n-1]=0;
}
void summa(int n,const poly &a,poly &b){
    for(int i=1;i<n;i++)
        b[i]=1ll*a[i-1]*inv(i)%mod;
    b[0]=0;
}
void ln(int n,const poly &f,poly &g){
    poly A,invs;
    dao(n,f,A);inv(n,f,invs);
    calc(n,n);NTT(A);NTT(invs);
    for(int i=0;i<limit;i++)
        A[i]=A[i]*invs[i]%mod;
    NTT(A,true);summa(n,A,g);
}
void exp(int n,const poly &f,poly &g){
    if(n==1) return(void)(g[0]=1);
    calc(n,n);poly lns(limit);
    exp((n+1)>>1,f,g);ln(n,g,lns);
    for(int i=0;i<n;i++)
        lns[i]=((i==0)-lns[i]+mod+f[i])%mod;
    NTT(lns);NTT(g);
    for(int i=0;i<limit;i++) g[i]=lns[i]*g[i]%mod;
    NTT(g,true);
    for(int i=n;i<limit;i++) g[i]=0;
}
poly x,y;
int n;
int main(){
    scanf("%d",&n);
    for(int i=0;i<n;i++)
        scanf("%lld",&x[i]),x[i]%=mod;
    exp(n,x,y);
    for(int i=0;i<n;i++)
        printf("%lld ",y[i]%mod);
    return 0;
}

  1. T ( n ) = T ( n 2 ) + Θ ( n log ⁡ 2 n ) T(n)=T\left(\dfrac n2\right)+\Theta(n\log_2 n) T(n)=T(2n)+Θ(nlog2n)  因而 f ( n ) = Θ ( n log ⁡ 2 n ) > Θ ( n l o g 2 1 ) = Θ ( 1 ) f(n)=\Theta(n\log_2 n)>\Theta(n^{log_2 1})=\Theta(1) f(n)=Θ(nlog2n)>Θ(nlog21)=Θ(1),故 T ( n ) = f ( n ) = Θ ( n log ⁡ 2 n ) T(n)=f(n)=\Theta(n\log_2 n) T(n)=f(n)=Θ(nlog2n) ↩︎

你可能感兴趣的:(快速数论变换,多项式)