• 多项式全家桶


    多项式全家桶(简单基础小清新版本)

    形式幂级数的导数和积分

    [F'(x)=sum_{i=0}^{infty} (i+1) a_{i+1}x^i\ int F(x) = (sum_{i=1}^{infty} frac{a_{i-1}}{i} x^i) +C ]

    注意求导后积分会导致常数项信息丢失。

    泰勒展开

    对于函数 (G),考虑选取一点 (x_0),用关于 (x-x_0) 的多项式 (F(x)) 来拟合多项式 (G)。通俗地讲,就是用一个幂级数 (F(x)) 来拟合 (G(x))

    [F(x)=sum_{i=0}^{infty} frac{G^{(i)} (x_0)}{i!} (x-x_0)^i ]

    我们取 (x_0=0) 的特殊情形有麦克劳林公式

    [F(x)=sum_{i=0}^{infty} frac{G^(i)(0)}{i!} x^i ]

    常见泰勒展开

    [e^x=sum_{i=0}^{infty} frac{x^i}{i!}\ ln (x+1)=sum_{i=0}^{infty} (-1)^{i-1} frac{x^i}{i} ]

    牛顿迭代

    给定幂级数 (B(x)),求另一个幂级数 (A(x)) 使得 (B(A(x))equiv 0pmod {x^n})。前提:(B(A(X))) 收敛。

    设我们已经取得了 (frac{n}{2}) 时的答案,设为 (A_0(x))。我们有 (A(x)equiv A_0(x) pmod {x^{frac{n}{2}}}),平方一下就有 ((A(x)-A_0(x)equiv 0 pmod {x^n})

    考虑对 (B(A(x))) 泰勒展开,以 (A_0(x)) 为展开的点,然后带入上述式子,最终可以解得

    [A(x)equiv A_0(x) - frac{B(A_0(x))}{B'(A_0(x))} pmod {x^n} ]

    形式幂级数乘法逆

    给定幂级数 (G(x)),求幂级数满足 (G(x)F(x)equiv 1 pmod {x^n})

    设我们已经递归求得了 (F_0(x)),即 (frac{n}{2}) 时的答案。有两种做法。

    1. 平方法

      [(F(x)-F_0(x))^2 equiv 0\ F^2(x)-2F(x)F_0(x)+F_0^2(x) equiv 0\ G(x)F^2(x)-2G(x)F(x)F_0(x)+GF_0^2(x) equiv 0\ F(x)-2F_0(x)+G(x)F_0^2(x)equiv 0\ f(x)equiv 2F_0(x) - G(x)F_0^2(x) ]

    2. 牛顿迭代法

      (H(F(x))=F(x)-G(x)-1),即求 (H(F(x))equiv 0 pmod x^n)(F(x))

      [egin{aligned} F(x)&equiv F_0-frac{H(F_0(x))}{H'(F_0(x))}\ F(x)&equiv F_0-frac{G(x)F_0(x)-1}{frac{1}{F_0(x)}}\ &equiv 2F_0-G(x)F_0^2(x) end{aligned} ]

    可以用 (O(nlog n)) 递归求解。

    形式幂级数对数函数

    给定幂级数 (G(x)),求幂级数满足 (F(x)equiv ln(G(x)) pmod {x^n})

    [egin{aligned} F(x) &equiv ln(G(x))\ F'(x) &equiv frac{G'(x)}{G(x)}\ F(x) &equiv int frac{G'(x)}{G(x)} end{aligned} ]

    注意常数项为 0。

    可以用 (O(log n)) 解决。

    形式幂级数指数函数

    给定幂级数 (G(x)),求幂级数 (F(x)) 使得 (F(x)equiv exp(G(x)) pmod {x^n})

    考虑牛顿迭代法。设 (H(F(x))=ln(F(x))-G(x))。则我们要求 (H(F(x))equiv 0pmod {x^n})。设我们已经求出 (frac{n}{2}) 的答案 (F_0(x))

    [egin{aligned} F(x) &equiv F_0(x)-frac{H(F_0(x))}{H'(F_0(x))}\ &equiv F_0(x)-frac{ln(F_0(x)-G(x)}{frac{1}{F_0(x)}}\ &equiv F_0(x)(1-ln(F_0(x))+G(x)) end{aligned} ]

    可以用 (O(nlog n)) 解决。

    形式幂级数快速幂

    给定幂级数 (G(x)),求幂级数 (F(x)equiv G^k(x) pmod{x^n})

    [egin{aligned} ln(F(x)) &equiv kln(G(x))\ F(x) &equiv exp(kln(G(x))) mod x^n end{aligned} ]

    可以用 (O(nlog n)) 解决。

    还可以用快速幂解决,常数会更小但是多一个 (log)

    形式幂级数开平方

    给定幂级数 (G(x)),求幂级数 (F(x)equiv sqrt{G(x)} pmod {x^n})。设已经解决了 (frac{n}{2}) 的答案 (F_0(x)),然后我们考虑用平方法。

    [F^2(x)-2F(x)F_0(x)+f_0^2(x)equiv 0\ G(x)-2F(x)F_0(x)+F_0^2(x)equiv 0\ F(x)equiv frac{G(x)+F_0^{2}(x)}{2F_0(x)} ]

    全家桶

    namespace Poly {
    	const int mod=998244353,gg=3,ig=332748118;
    	int lim,r[N],a[N],b[N],c[N],d[N],e[N],h[N];
    	void init(int n) {
    		int l=0;
    		for(lim=1;lim<=n;lim<<=1,l++);
    		rep(i,0,lim) r[i]=(r[i>>1]>>1)|((i&1)<<l-1);
    	}
    	int pls(int x,int y) {return x+=y,x>=mod?x-mod:x;}
    	int mns(int x,int y) {return x-=y,x<0?x+=mod:x;}
    	int ksm(int x,int y,int ret=1) {
    		while(y) {
    			if(y%2) ret=ret*x%mod;
    			x=x*x%mod, y>>=1;
    		}
    		return ret;
    	}
    	void ntt(int *f,int lim,int t) {
    		rep(i,0,lim-1) if(i<r[i]) swap(f[i],f[r[i]]);
    		for(int len=1;len<lim;len<<=1) {
    			int dw=ksm(t>0?gg:ig,(mod-1)/(len*2));
    			for(int i=0;i<lim;i+=len*2) {
    				int w=1;
    				for(int j=0;j<len;j++,w=w*dw%mod) {
    					int x=f[i+j], y=w*f[i+j+len]%mod;
    					f[i+j]=pls(x,y), f[i+j+len]=mns(x,y);
    				}
    			}
    		}
    		if(t==-1) {
    			int iv=ksm(lim,mod-2);
    			rep(i,0,lim) f[i]=f[i]*iv%mod;
    		}
    	}
    	
    	void _mul(int *f,int *g,int len) {
    		init(len);
    		ntt(f,lim,1), ntt(g,lim,1);
    		rep(i,0,lim-1) f[i]=f[i]*g[i]%mod;
    		ntt(f,lim,-1);
    	}
    	void _dev(int *f,int *g,int len) {
    		rep(i,1,len-1) f[i-1]=i*g[i]%mod; f[len-1]=0;
    	}
    	void _int(int *f,int *g,int len) {
    		rep(i,1,len-1) f[i]=ksm(i,mod-2)*g[i-1]%mod; f[0]=0;
    	}
    	void _inv(int *f,int *g,int len) {
    		if(len==1) {f[0]=ksm(g[0],mod-2); return;}
    		_inv(f,g,(len+1)/2);
    		init(len*2);
    		rep(i,0,len-1) c[i]=g[i]; rep(i,len,lim) c[i]=0;
    		ntt(c,lim,1), ntt(f,lim,1);
    		rep(i,0,lim-1) f[i]=mns(2,f[i]*c[i]%mod)*f[i]%mod;
    		ntt(f,lim,-1);
    		rep(i,len,lim-1) f[i]=0;
    	}
    	void _ln(int *f,int *g,int len) {
    		memset(a,0,sizeof(a)), memset(b,0,sizeof(b));
    		_dev(a,g,len), _inv(b,g,len);
    		_mul(a,b,len*2), _int(f,a,len);
    		rep(i,len,lim) f[i]=0;
    	}
    	void _exp(int *f,int *g,int len) {
    		if(len==1) {f[0]=1; return;}
    		_exp(f,g,(len+1)/2);
    		init(len*2);
    		rep(i,0,lim) d[i]=e[i]=0;
    		rep(i,0,len-1) d[i]=g[i];
    		_ln(e,f,len);
    		ntt(f,lim,1), ntt(d,lim,1), ntt(e,lim,1);
    		rep(i,0,lim-1) f[i]=(1-e[i]+d[i]+mod)%mod*f[i]%mod;
    		ntt(f,lim,-1); rep(i,len,lim-1) f[i]=0;
    	}
    	void _pow(int *f,int *g,int len,int k) {
    		memset(h,0,sizeof(h));
    		_ln(h,g,len);
    		rep(i,0,len-1) h[i]=h[i]*k%mod; rep(i,len,lim) h[i]=0;
    		_exp(f,h,len);
    		rep(i,len,lim) f[i]=0;
    	}
    	void _sqrt(int *f,int *g,int len) {
    		if(len==1) {f[0]=1; return;}
    		_sqrt(f,g,(len+1)/2);
    		init(len*2);
    		rep(i,0,lim) d[i]=e[i]=0;
    		_inv(e,f,len);
    		rep(i,0,len-1) d[i]=g[i];
    		ntt(f,lim,1), ntt(d,lim,1), ntt(e,lim,1);
    		rep(i,0,lim-1) f[i]=(d[i]+f[i]*f[i]%mod)%mod*e[i]%mod*ksm(2,mod-2)%mod;
    		ntt(f,lim,-1); rep(i,len,lim-1) f[i]=0;
    	}
    }
    
  • 相关阅读:
    LinkedList源码解析
    HashMap源码解析
    HashMap和Hashtable区别
    arcgis api for js 之网络分析服务发布
    arcgis api for js 之发布要素服务
    arcis api for js 值 3.17 本地部署
    ArcGIS 产品体系结构
    layui select下拉框选项不显示
    windows10企业版2016长期服务版激活
    PHP常见的输出语句
  • 原文地址:https://www.cnblogs.com/TetrisCandy/p/14501588.html
Copyright © 2020-2023  润新知