多项式全家桶
多项式乘法逆
设 \(F*G\equiv1\ (mod\ x^n)\)
递归处理
设 \(H*F\equiv1\ (mod\ x^k)\),考虑推出 \(H'*F\equiv1\ (mod\ x^{2k})\)
\[H*F\equiv1\ (mod\ x^k)
\]
\[H^2F^2-2HF+1\equiv0\ (mod\ x^{2k})
\]
\[H^2F-2H+H'=0\ (mod\ x^{2k})
\]
\[H'=2H-H^2F\ (mod\ x^{2k})
\]
多项式对数
设 \(f(x)=ln(x)\)
\[B(x)=f(A(x))
\]
\[B'(x)=f'(A(x))A'(x)
\]
\[B'(x)=\frac{A'(x)}{A(x)}
\]
\[B(x)=\int\frac{A'(x)}{A(x)}
\]
多项式exp
\[B(x)=e^{A(x)}
\]
\[ln(B(x))-A(x)=0
\]
设 \(G(B(x))=ln(B(x))-A(x)\),则相当于求 \(G\) 的零点。
递归求解。
当 \(len=1\) 时,由于 \(A_0=0\),所以 \(B_0=1\)。
假设已知 \(G(B_0(x))\equiv 0\ (mod\ x^k)\),推出 \(G(B(x))\equiv 0\ (mod\ x^{2k})\)。
写出 \(G(B(x))\) 在 \(B_0(x)\) 处的泰勒展开
\[G(B(x))\equiv G(B_0(x))+G'(B_0(x))(B(x)-B_0(x))+\cdots
\]
因为 \(B(x)\equiv B_0(x)\ (mod\ x^{k})\),则 \((B(x)-B_0(x))^2\equiv0(mod\ x^{2k})\)
所以泰勒展开的第 \(2\) 到 \(inf\) 项在模 \(x^{2k}\) 的意义下都是 \(0\)。
\[0\equiv G(B(x))\equiv G(B_0(x))+G'(B_0(x))(B(x)-B_0(x))
\]
\[B(x)=B_0(x)-\frac{G(B_0(x))}{G'(B_0(x))}
\]
由于在定义 \(G\) 的时候, \(B(x)\) 为变量,\(A(x)\) 为常数,所以
\[G'(B_0(x))=\frac1{B_0(x)}
\]
\[\therefore B(x)=B_0(x)-B_0(ln(B_0(x))-A(x))
\]
\[B(x)=B_0(1-ln(B_0(x))+A(x))
\]
\(n^2 \ln,\exp\)
设 \(A(x)=e^{B(x)},B(x)=\ln (A(x))\)
\[B'(x)=\frac{A'(x)}{A(x)}
\]
\[A(x)xB'(x)x=xA'(x)
\]
\[\because x(x^k)'=kx^k
\]
\[\therefore \sum_{i=1}^n iB_iA_{n-i}=nA_n
\]
\[A_n=\frac 1n\sum_{i=1}^n iB_iA_{n-i}
\]
\[B_n=A_n-\frac 1n\sum_{i=1}^{n-1} iB_iA_{n-i}
\]
#include<bits/stdc++.h>
using namespace std;
template<typename T>
inline void Read(T &n){
char ch; bool flag=false;
while(!isdigit(ch=getchar()))if(ch=='-')flag=true;
for(n=ch^48;isdigit(ch=getchar());n=(n<<1)+(n<<3)+(ch^48));
if(flag)n=-n;
}
enum{
MAXN = 100005,
MOD = 998244353,
G = 3
};
inline int ksm(int base, int k=MOD-2){
int res=1;
while(k){
if(k&1)
res = 1ll*res*base%MOD;
base = 1ll*base*base%MOD;
k >>= 1;
}
return res;
}
inline int inc(int a, int b){
a += b;
if(a>=MOD) a -= MOD;
return a;
}
inline int dec(int a, int b){
a -= b;
if(a<0) a += MOD;
return a;
}
inline void iinc(int &a, int b){a = inc(a,b);}
inline void ddec(int &a, int b){a = dec(a,b);}
inline void upd(int &a, long long b){a = (a+b)%MOD;}
int wn[MAXN<<2], tr[MAXN<<2];
inline int prework(int n){
int len=1; while(len<=n) len<<=1;
wn[0] = 1; wn[1] = ksm(G,(MOD-1)/len);
for(register int i=2; i<=len; i++) wn[i] = 1ll*wn[i-1]*wn[1]%MOD;
for(register int i=1; i<len; i++) tr[i] = (tr[i>>1]>>1)|((i&1)?(len>>1):0);
return len;
}
typedef vector<int> poly;
inline void ntt(poly &f, int n, int flag){
for(register int i=0; i<n; i++) if(i<tr[i]) swap(f[i],f[tr[i]]);
for(register int len=2; len<=n; len<<=1){
int base = flag*n/len;
for(register int l=0; l<n; l+=len){
int now = flag==1?0:n;
for(register int i=l; i<l+len/2; i++){
int tmp = 1ll*f[i+len/2]*wn[now]%MOD;
f[i+len/2] = dec(f[i],tmp);
iinc(f[i],tmp);
now += base;
}
}
}
if(flag==-1){
int inv = ksm(n);
for(register int i=0; i<n; i++) f[i] = 1ll*f[i]*inv%MOD;
}
}
poly Inv(poly f, int n){
if(n==1){poly res(1); res[0] = ksm(f[0]); return res;}
poly h = Inv(f,n+1>>1), tmpf(n);
for(register int i=0; i<n; i++) tmpf[i] = f[i];
int len = prework(n<<1);
h.resize(len); tmpf.resize(len);
ntt(h,len,1); ntt(tmpf,len,1);
for(register int i=0; i<len; i++) h[i] = dec(inc(h[i],h[i]),1ll*h[i]*h[i]%MOD*tmpf[i]%MOD);
ntt(h,len,-1);
h.resize(n); tmpf.clear();
return h;
}
inline poly Dlt(poly f, int n){
poly res(n-1);
for(register int i=0; i<n-1; i++) res[i] = 1ll*(i+1)*f[i+1]%MOD;
return res;
}
inline poly Sigma(poly f, int n){
poly res(n+1), inv(n+1); inv[1] = 1;
for(register int i=2; i<=n; i++) inv[i] = 1ll*(MOD-MOD/i)*inv[MOD%i]%MOD;
for(register int i=0; i<n; i++) res[i+1] = 1ll*inv[i+1]*f[i]%MOD;
return res;
}
inline poly Ln(poly f, int n){
poly dltf = Dlt(f,n), res = Inv(f,n);
int len = prework(n+n);
dltf.resize(len); res.resize(len);
ntt(dltf,len,1); ntt(res,len,1);
for(register int i=0; i<len; i++) res[i] = 1ll*res[i]*dltf[i]%MOD;
ntt(res,len,-1); res.resize(n);
res = Sigma(res,n); res.resize(n);
return res;
}
poly Exp(poly f, int n){
if(n==1){poly res(1); res[0] = 1; return res;}
poly res = Exp(f,n+1>>1); res.resize(n);
poly lnres = Ln(res,n);
int len = prework(n*1.5+1); poly tmpf(len);
for(register int i=0; i<n; i++) tmpf[i] = f[i];
res.resize(len); lnres.resize(len);
ntt(res,len,1); ntt(lnres,len,1); ntt(tmpf,len,1);
for(register int i=0; i<len; i++) res[i] = 1ll*res[i]*dec(inc(1,tmpf[i]),lnres[i])%MOD;
ntt(res,len,-1); res.resize(n);
return res;
}
int main(){
int n; Read(n);
poly f(n);
for(register int i=0; i<n; i++) Read(f[i]);
poly g = Exp(f,n);
for(register int i=0, tp=g.size(); i<tp; i++) printf("%d ",g[i]);puts("");
return 0;
}