1. 程式人生 > 其它 >MongoDB 複製集機制及原理

MongoDB 複製集機制及原理

多項式乘法逆

\(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)) \]
#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;
}