MongoDB 複製集機制及原理
阿新 • • 發佈:2021-06-16
多項式乘法逆
設 \(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
設 \(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})\)
所以泰勒展開的第 \(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)) \]#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; }