前置芝士:微积分(有所了解即可)(可以看看这篇,写得非常详细我看了两章就看不下去了)
以下都是一些简单的教程切莫当真,仅供理解,建议看更严谨的
导数:对于一个函数$f(x)$,它的导数$f'(x)$为一个新的函数。简单理解的话,$f'(x)$表示在原函数图像上该点切线的斜率,记为$\frac{dy}{dx}$或$\frac{d}{dx}f(x)$
积分:对于一个导数$f'(x)$,它所对应的原函数为它的积分,记为$\int f'(x)dx$
对于一个多项式$F(x)=\sum_{i=0}^na_ix^i$来说(一个多项式实际上可以看做一个函数),它的导数和积分如下
$$F'(x)=\sum_{i=1}^nia_ix^{i-1}$$
$$\int F(x)=\sum_{i=1}^n\frac{a_ix^{i+1}}{i+1}$$
这两个是可以$O(n)$计算的,可以互相转换
然后我们要计算$ln\ F$,首先因为$ln'(x)=\frac{1}{x}$,而这里是一个多项式,根据链式法则(我也不知道什么东西),$\frac{dy}{dx}=\frac{dy}{du}\frac{du}{dx}$,然后把$F(x)$带进去,得$$\frac{d}{dx}ln(F(x))=\frac{d}{dF(x)}ln(F(x))\frac{dF(x)}{dx}$$
$$\frac{d}{dx}ln(F(x))=\frac{1}{F}F'$$
$$ln(F(x))\equiv \int F'F^{-1}\pmod{x^n}$$
求导和积分的运算代码挺短的……然后剩下的基本就是多项式板子了
1 //minamoto 2 #include<iostream> 3 #include<cstdio> 4 #include<algorithm> 5 #define swap(x,y) (x^=y,y^=x,x^=y) 6 #define mul(x,y) (1ll*x*y%P) 7 #define add(x,y) (x+y>=P?x+y-P:x+y) 8 #define dec(x,y) (x-y<0?x-y+P:x-y) 9 using namespace std; 10 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 11 char buf[1<<21],*p1=buf,*p2=buf; 12 inline int read(){ 13 #define num ch-'0' 14 char ch;bool flag=0;int res; 15 while(!isdigit(ch=getc())) 16 (ch=='-')&&(flag=true); 17 for(res=num;isdigit(ch=getc());res=res*10+num); 18 (flag)&&(res=-res); 19 #undef num 20 return res; 21 } 22 char sr[1<<21],z[20];int K=-1,Z; 23 inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;} 24 inline void print(int x){ 25 if(K>1<<20)Ot();if(x<0)sr[++K]=45,x=-x; 26 while(z[++Z]=x%10+48,x/=10); 27 while(sr[++K]=z[Z],--Z);sr[++K]=' '; 28 } 29 const int N=400005,P=998244353; 30 inline int ksm(int a,int b){ 31 int res=1; 32 while(b){ 33 if(b&1) res=mul(res,a); 34 a=mul(a,a),b>>=1; 35 } 36 return res; 37 } 38 int n,r[N],A[N],B[N],C[N],D[N],F[N],G[N],O[N]; 39 void NTT(int *A,int type,int len){ 40 int limit=1,l=0; 41 while(limit<len) limit<<=1,++l; 42 for(int i=0;i<limit;++i) 43 r[i]=(r[i>>1]>>1)|((i&1)<<(l-1)); 44 for(int i=0;i<limit;++i) 45 if(i<r[i]) swap(A[i],A[r[i]]); 46 for(int mid=1;mid<limit;mid<<=1){ 47 int R=mid<<1,Wn=ksm(3,(P-1)/R);O[0]=1; 48 for(int j=1;j<limit;++j) O[j]=mul(O[j-1],Wn); 49 for(int j=0;j<limit;j+=R){ 50 for(int k=0;k<mid;++k){ 51 int x=A[j+k],y=mul(O[k],A[j+k+mid]); 52 A[j+k]=add(x,y),A[j+k+mid]=dec(x,y); 53 } 54 } 55 } 56 if(type==-1){ 57 reverse(A+1,A+limit); 58 for(int i=0,inv=ksm(limit,P-2);i<limit;++i) 59 A[i]=mul(A[i],inv); 60 } 61 } 62 void Inv(int *a,int *b,int len){ 63 if(len==1) return (void)(b[0]=ksm(a[0],P-2)); 64 Inv(a,b,len>>1);int l=len<<1; 65 for(int i=0;i<len;++i) C[i]=a[i],D[i]=b[i]; 66 NTT(C,1,l),NTT(D,1,l); 67 for(int i=0;i<l;++i) C[i]=mul(mul(C[i],D[i]),D[i]); 68 NTT(C,-1,l); 69 for(int i=0;i<len;++i) b[i]=dec(add(b[i],b[i]),C[i]); 70 } 71 void Direv(int *A,int *B,int len){ 72 //求导 73 for(int i=1;i<len;++i) B[i-1]=mul(A[i],i);B[len-1]=0; 74 } 75 void Inter(int *A,int *B,int len){ 76 //积分 77 for(int i=1;i<len;++i) B[i]=mul(A[i-1],ksm(i,P-2)),B[0]=0; 78 } 79 void Ln(int *a,int *b,int len){ 80 Direv(a,A,len),Inv(a,B,len);int l=len<<1; 81 NTT(A,1,l),NTT(B,1,l); 82 for(int i=0;i<l;++i) A[i]=mul(A[i],B[i]); 83 NTT(A,-1,l),Inter(A,b,len); 84 } 85 int main(){ 86 // freopen("testdata.in","r",stdin); 87 n=read(); 88 for(int i=0;i<n;++i) F[i]=read(); 89 int len;for(len=1;len<n;len<<=1); 90 Ln(F,G,len); 91 for(int i=0;i<n;++i) print(G[i]); 92 Ot(); 93 return 0; 94 }