给定一个\(n-1\)次多项式\(A(x)\),求一个\(mod\, x^n\)下的多项式\(G(x)\),满足\(G(x)≡ln A(x)\)
前置芝士:微积分
我们设\(G(F(x))=F(A(x))\),\(F(x)=ln(x)\)
对两边同时求导得到
\(G'(x)=f'(A(x))A'(x)\)
由于\(F'(x)=\frac{1}{x}\)(记住或者现推都行)
\(G'(x)=\frac{A'(x)}{A(x)}\)
多项式求逆+求导+积分就好了
#include<bits/stdc++.h> using namespace std; namespace red{ #define int long long #define y1 miao #define eps (1e-8) inline int read() { int x=0;char ch,f=1; for(ch=getchar();(ch<'0'||ch>'9')&&ch!='-';ch=getchar()); if(ch=='-') f=0,ch=getchar(); while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return f?x:-x; } const int N=4e5+10,p=998244353; int n; int a[N],g[N],c[N]; int da[N],inva[N]; int pos[N]; inline int fast(int x,int k) { int ret=1; while(k) { if(k&1) ret=ret*x%p; x=x*x%p; k>>=1; } return ret; } inline void deriva(int *a,int *b,int n) { for(int i=1;i<n;++i) b[i-1]=a[i]*i%p; b[n-1]=0; } inline void integral(int *a,int n) { for(int i=n-1;i;--i) a[i]=a[i-1]*fast(i,p-2)%p; a[0]=0; } inline void ntt(int limit,int *a,int inv) { for(int i=0;i<limit;++i) if(i<pos[i]) swap(a[i],a[pos[i]]); for(int mid=1;mid<limit;mid<<=1) { int Wn=fast(3,(p-1)/(mid<<1)); for(int r=mid<<1,j=0;j<limit;j+=r) { int w=1; for(int k=0;k<mid;++k,w=w*Wn%p) { int x=a[j+k],y=w*a[j+k+mid]%p; a[j+k]=x+y; if(a[j+k]>=p) a[j+k]-=p; a[j+k+mid]=x-y; if(a[j+k+mid]<0) a[j+k+mid]+=p; } } } if(inv) return; inv=fast(limit,p-2);reverse(a+1,a+limit); for(int i=0;i<limit;++i) a[i]=a[i]*inv%p; } inline void poly_inv(int pw,int *a,int *b) { if(pw==1) {b[0]=fast(a[0],p-2);return;} poly_inv((pw+1)>>1,a,b); int len=0,limit=1; while(limit<(pw<<1)) limit<<=1,++len; for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(len-1)); for(int i=0;i<pw;++i) c[i]=a[i]; for(int i=pw;i<limit;++i) c[i]=0; ntt(limit,c,1);ntt(limit,b,1); for(int i=0;i<limit;++i) b[i]=((2-c[i]*b[i]%p)+p)%p*b[i]%p; ntt(limit,b,0); for(int i=pw;i<limit;++i) b[i]=0; } inline void main() { n=read(); for(int i=0;i<n;++i) a[i]=read(); deriva(a,da,n); poly_inv(n,a,inva); int len=0,limit=1; while(limit<(n<<1)) limit<<=1,++len; for(int i=0;i<limit;++i) pos[i]=(pos[i>>1]>>1)|((i&1)<<(len-1)); ntt(limit,da,1);ntt(limit,inva,1); for(int i=0;i<limit;++i) g[i]=da[i]*inva[i]%p; ntt(limit,g,0); integral(g,n); for(int i=0;i<n;++i) printf("%lld ",g[i]); } } signed main() { red::main(); return 0; }
来源:https://www.cnblogs.com/knife-rose/p/12131352.html