多项式对数函数|指数函数
这个思路就是先求导然后再积分,这样就可以得到一个式子,对于多项式对数函数,我们就可以直接求解了,然后对于多项式指数函数还需要使用分治fft。
多项式对数:
#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline int read()
{char x='\0';int fh=1,sum=0;for(x=getchar();x<'0'||x>'9';x=getchar())if(x=='-')fh=-1;for(;x>='0'&&x<='9';x=getchar())sum=sum*10+x-'0';return fh*sum;
}
const int N=400009;
const int mod=998244353;
int n,m;
inline int ksm(int a,int b)
{int sum=1;while(b){if(b&1)sum=1LL*sum*a%mod;b>>=1;a=1LL*a*a%mod;}return sum;
}
int F[N],G[N],rev[N],l,tt;
inline void getl(int len)
{for(l=1,tt=0;l<=len;l<<=1)tt++;for(int i=0;i<l;i++) rev[i]=(rev[i>>1]>>1)|((i&1)<<(tt-1));
}
inline void NTT(int *P,int op)
{for(int i=0;i<l;i++)if(i<rev[i])swap(P[i],P[rev[i]]);for(int i=1;i<l;i<<=1){int wn=ksm(3,(mod-1)/(i<<1));if(op<0)wn=ksm(wn,mod-2);for(int j=0,p=i<<1;j<l;j+=p){for(int k=0,w=1;k<i;k++,w=1ll*w*wn%mod){int x=P[j+k],y=1LL*P[j+i+k]*w%mod;P[j+k]=(x+y)%mod,P[j+i+k]=(x-y+mod)%mod;} }}if(op<0)for(int i=0,u=ksm(l,mod-2);i<l;i++)P[i]=1LL*P[i]*u%mod;
}
int C[N],D[N];
inline void getinv(int *f,int *g,int n)
{if(n==1)return g[0]=ksm(f[0],mod-2),void();getinv(f,g,n>>1);getl(n);for(int i=0;i<n;i++) C[i]=f[i],D[i]=g[i];for(int i=n;i<l;i++) C[i]=D[i]=0; NTT(C,1),NTT(D,1);for(int i=0;i<l;i++) C[i]=1LL*C[i]*D[i]%mod*D[i]%mod; NTT(C,-1);for(int i=0;i<n;i++) g[i]=((2LL*g[i]%mod-C[i])%mod+mod)%mod;
}
void dao(int *A,int *B,int len)
{for(int i=1;i<len;i++)B[i-1]=1LL*i*A[i]%mod;B[len-1]=0;
}
void jifen(int *A,int *B,int len)
{for(int i=1;i<len;i++)B[i]=1LL*A[i-1]*ksm(i,mod-2)%mod;B[0]=0;
}
int A[N],B[N];
void getln(int *f,int *g,int n)
{dao(f,A,n);getinv(f,B,n);getl(n),NTT(A,1),NTT(B,1);for(int i=0;i<l;i++)A[i]=1LL*A[i]*B[i]%mod;NTT(A,-1);jifen(A,g,n);
}
int main()
{n=read();for(int i=0;i<n;i++)F[i]=read();for(m=1;m<=n;m<<=1); getln(F,G,m);for(int i=0;i<n;i++) printf("%d ",G[i]);return 0;
}
细节:
- 首先需要一个封装好的NTT,然后每次需要重新求解l和rev
- 对于中间数组需要用到ABCD4个,但是使用过程中不能直接清空,所以在每次使用的时候要将空余的位置设置为0,保证有效位置都是正确的
- 过程中直接传递指针,就可以递归求解了。