多项式对数函数(多项式 ln)

前置知识

\(\ln\) 求导

\(\ln'(t)\)

结论

\[\ln'(t)=\frac{1}{t} \]

证明

设:

\[\frac{1}{\varepsilon}\ln(1+\frac{\varepsilon}{t})=k \]

\[\frac{1}{k\varepsilon}\ln(1+\frac{\varepsilon}{t})=1 \]

\[(1+\frac{\varepsilon}{t})^{\frac{1}{k\varepsilon}}=e=\lim_{x\to\infty}\limits (1+\frac{1}{x})^x \]

那么就得到了:

\[\begin{cases} \frac{\varepsilon}{t}=\frac{1}{x}\\ \frac{1}{k\varepsilon}=x \end{cases} \]

相乘得到:

\[\frac{1}{kt}=1 \]

那么:

\[k=\frac{1}{t} \]

\[\ln'(t)=\frac{1}{t} \]

至此,证毕。


多项式求导

\(f'(x)\)

结论

\([x^t]f(x)\cdot x^t\to t\cdot [x^t]f(x)\cdot x^{t-1}\)

写得和蔼一点就是:\(a_i\cdot x^{i}\to a_i\cdot i\cdot x^{i-1}\)

积分同理,即回带。

证明

稍微咕一下,就一下。


复合函数求导法则

结论

\(h(x)=f[g(x)],h'(x)=f'[g(x)]\cdot g'(x)\)

证明

稍微咕一下,就

多项式求 \(\ln\)

\(\ln(f(x))=g(x)\)

\[g'(x)=\ln'(f(x))\cdot f'(x)=\frac{1}{f(x)}\cdot f'(x) \]


正题

由前面我们已经发现了 \(\ln\) 函数的优美性质,其导数为 \(\frac{1}{x}\)

结合复合函数求导公式,我们就可以干一些好玩的事情。

对于:

\[\ln A(x)\equiv B(x)\pmod p \]

我们就可以通过复合函数求导得到:

\[\ln' A(x) \cdot A'(x)\equiv B'(x) \]

\[\frac{1}{A(x)}\cdot A'(x)\equiv B'(x) \]

对于给定的 \(A\),第一项,我们可以由求逆得到,第二项,由多项式求导得到。

于是我们就可以将两者卷起来求得 \(B\) 的导数,然后将其转回去得到系数。

这里有个有趣的小细节,就是实际上,转回去之后,我们会不知道常数项,这应该怎么办呢?实际上常数项就是 \(0\),至于为什么,之后在 exp 部分会详细证明。


代码

#include <stdio.h>
#define LL long long
using namespace std;
const int N=3e5+3;
const int M=998244353;
const int K=3;
inline int rin()
{
    int s=0;
    bool bj=false;
    char c=getchar();
    for(;(c>'9'||c<'0')&&c!='-';c=getchar());
    if(c=='-')bj=true,c=getchar();
    for(;c>='0'&&c<='9';c=getchar())s=(s<<1)+(s<<3)+(c^'0');
    if(bj)s=-s;
    return s;
}
inline int prpr(int x,int y){return 1LL*x*y%M;}
inline int ksm(int x,int y){int ans=1;for(;y;y>>=1){if(y&1)ans=prpr(ans,x);x=prpr(x,x);}return ans;}
inline void jh(int &x,int &y){if(x!=y)x^=y^=x^=y;return;}

const int Kr=ksm(K,M-2);

int num[N];
int lens;
inline void init(int L)
{
    int lg=0;
    for(lens=1;lens<L;lens<<=1)lg++;
    for(int i=0;i<lens;i++)num[i]=((num[i>>1]>>1)|((i&1)<<lg-1));
    return;
}

inline void NTT(int *a,int tag)
{
    for(int i=0;i<lens;i++)if(i>num[i])jh(a[i],a[num[i]]);
    for(int i=1;i<lens;i<<=1)
    {
        int Gyq=ksm(tag?K:Kr,(M-1)/(i<<1));
        for(int j=0;j<lens;j+=(i<<1))
        {
            int Zjj=1;
            for(int k=0;k<i;k++,Zjj=prpr(Zjj,Gyq))
            {
                int x=a[j+k],y=prpr(a[j+k+i],Zjj);
                a[j+k]=(x+y)%M;
                a[j+k+i]=(x-y+M)%M;
            }
        }
    }
    if(!tag)
    {
        int Gyq=ksm(lens,M-2);
        for(int i=0;i<lens;i++)a[i]=prpr(a[i],Gyq);
    }
    return;
}

int Alpha[N];
inline void inv(int *a,int *b,int L)
{
    if(L==1){b[0]=ksm(a[0],M-2);return;}
    inv(a,b,(L+1)>>1);
    init((L<<1)-1);
    for(int i=0;i<L;i++)Alpha[i]=a[i];
    for(int i=L;i<lens;i++)Alpha[i]=0;
    NTT(Alpha,1);
    NTT(b,1);
    for(int i=0;i<lens;i++)b[i]=prpr(b[i],2-prpr(Alpha[i],b[i]));
    NTT(b,0);
    for(int i=L;i<lens;i++)b[i]=0;
    return;
}

inline void der(int *a,int L){for(int i=1;i<L;i++)a[i-1]=prpr(a[i],i);for(int i=L;i<lens;i++)a[i]=0;return;}

int n;
int a[N];
int b[N];

int sl[N];
int sr[N];
int main()
{
    n=rin()-1;
    for(int i=0;i<=n;i++)a[i]=rin();
    inv(a,b,n+1);
    init(n+n+1);
    der(a,n+1);
    NTT(a,1);
    NTT(b,1);
    for(int i=0;i<lens;i++)b[i]=prpr(b[i],a[i]);
    NTT(b,0);
    
    sl[0]=sr[0]=1;
    for(int i=1;i<=n;i++)sl[i]=prpr(sl[i-1],i);
    sr[n]=ksm(sl[n],M-2);
    for(int i=n-1;i>=1;i--)sr[i]=prpr(sr[i+1],i+1);
    for(int i=n;i>=1;i--)b[i]=prpr(prpr(b[i-1],sr[i]),sl[i-1]);
    b[0]=0;
    for(int i=0;i<=n;i++)printf("%d ",(b[i]%M+M)%M);printf("\n");
    return 0;
}

posted @ 2020-12-28 21:54  zjjws  阅读(1052)  评论(0编辑  收藏  举报