zoukankan      html  css  js  c++  java
  • [学习笔记] 牛顿迭代法

    泰勒展开

    假设我们有函数(f(x))(x)(x_0)处有(infty)阶导数。

    我们知道(f(x_0)) 的值

    我们希望构造一个多项式(g),使它尽可能逼近函数(f)

    • 那么就使它在(x_0)处的1~(infty)阶导数都与(f)相同,即:(f^{(n)}=g^{(n)}),那么一直到最后就有(f(x)=g(x))

    • 我们还原这个多项式:

    (egin{aligned}g(x)&=xi_0+f(x_0)+frac{f^{(1)}(x_0)}{1!}(x-x_0)^1+frac{f^{(2)}(x_0)}{2!}(x-x_0)^2+...+frac{f^{(n)}(x_0)}{n!}(x-x_0)^n\&=xi_0+f(x_0)+sum_{i=1}^{infty}frac{f^{(i)}(x_0)}{i!}(x-x_0)^iend{aligned})

    这即是泰勒展开。

    牛顿迭代法

    假设我们要求:(F(B(x))equiv0(mod x^{2^t}))(B(x))为多项式

    (B_t(x)equiv B(x)(mod x^{2^t}))

    首先,我们可以很容易的算出(B_0)

    假设我们已经求出了(B_{t-1})

    • 我们对(F(B_{t+1}(x)))(B_t)处进行泰勒展开。

    (egin{aligned}F(B_{t+1}(x))&=F(B_t(x))+sum_{i=1}^nfrac{F^{(i)}(B_t(x)) imes(B_{t+1}(x)-B_t(x))^i}{i!}\&=F(B_t(x))+frac{F'(B_t(x)) imes(B_{t+1}(x)-B_t(x))}{1!}end{aligned})

    因为 (F(B_t(x))equiv0(mod x^{2^t}))

    所以 ((B_{t+1}(x)-B_t(x))^n=0(nge2))

    • 把目标项单独移到左边:

    (B_{t+1}(x)=B_t(x)+frac{F(B_{t+1}(x))-F(B_t(x))}{F'(B_t(x))})

    • 又因为(F(B_{t+1}(x)))在模意义下等于0(定义),又有:

    (B_{t+1}(x)=B_t(x)-frac{F(B_{t}(x))}{F'(B_t(x))})

    这即使牛顿迭代法的式子。

    多项式求逆

    即求:(A(x) imes B(x)equiv1)(A)为原多项式系数)

    有:

    (F(B_t(x))=A(x) imes B_t(x)-1)

    • 代入牛顿迭代法的式子:

    (egin{aligned}B_{t+1}(x)&=B_t(x)-frac{A(x) imes B_t(x)-1}{A(x)}\&=B_t(x)-B_t(x) imes(A(x) imes B_{t}(x)-1)\&=-A(x) imes B_t^2(x)+2B_t(x)end{aligned})

    (因为(A imes Bequiv 1),所以除以(A)即是乘上(B)

    void Inv(int *f,int *g,int n){
    	int c[N];
        f[0]=pow(g[0],mod-2);
    	for (int l=2;l<n<<1;l<<=1){
    		Get(l<<1,0);
    		for (int i=0;i<l;i++) c[i]=g[i];
    		for (int i=l;i<L;i++) c[i]=0;
        	fft(f,1),fft(c,1);
    		for (int i=0;i<L;i++) f[i]=(2-1ll*c[i]*f[i])%mod*f[i]%mod;
    		fft(f,-1);
    		for (int i=l;i<L;++i) f[i]=0;
    	}
    }
    

    多项式求 (ln)

    即求:(ln A(x)=B(x))

    • 这次不需要用到牛顿迭代法,直接求导:

    (egin{aligned}ln A(x)&=B(x)\frac{A'(x)}{A(x)}&=B'(x)end{aligned})

    然后只要积分即可。

    void Qiud(int *f,int *g,int n){
    	f[n-1]=0;
    	for (int i=0;i<n-1;i++) f[i]=1ll*g[i+1]*(i+1)%mod;
    }
    void Jif(int *f,int *g,int n){
    	f[0]=0;
    	for (int i=1;i<n;i++) f[i]=1ll*g[i-1]*inv[i]%mod;
    }
    void Ln(int *f,int *g,int n){
    	int c[N],d[N];
    	for (int i=0;i<n;i++) c[i]=d[i]=0;
    	Inv(c,g,n),Qiud(d,g,n);
    	Get(n<<1);
    	for (int i=n;i<L;i++) c[i]=d[i]=0;
    	fft(c,1),fft(d,1);
    	for (int i=0;i<L;i++) d[i]=1ll*c[i]*d[i]%mod;
    	fft(d,-1);
    	Jif(f,d,n);
    }
    

    (exp)

    即求:(e^{A(x)}=B(x))

    • 我们先用(ln) 把exp给去掉:

    (A(x)=ln B(x))

    有:

    (F(B_t(x))=ln B(x)-A(x))

    • 套牛顿迭代法:

    (egin{aligned}B_{t+1}(x)&=B_t(x)-frac{ln B_t(x)-A(x)}{frac{1}{B_t(x)}}\&=B_t(x) imes(1-ln B_t(x)+A(x))end{aligned})

    • 时间复杂度是 (varTheta(nlog^2n))
    void Exp(int *f,int *g,int n){
    	int c[N],d[N];
    	f[0]=1;
    	for (int l=2;l<n<<1;l<<=1){
    		Ln(d,f,l);
    		Get(l<<1,0);
    		for (int i=0;i<l;i++) c[i]=g[i];
    		for (int i=l;i<L;i++) c[i]=d[i]=0;
    		fft(f,1),fft(c,1),fft(d,1);
    		for (int i=0;i<L;i++) f[i]=(1ll-d[i]+c[i])*f[i]%mod;
    		fft(f,-1);
    	}
    }
    

    以上就是全部内容了,刚发现没写过(FFT)的博客,待会儿补一下。

  • 相关阅读:
    不用IDE写C#的Hello World
    .NET中常见的内存泄露问题——GC、委托事件和弱引用
    .net微信公众号开发——群发消息
    C#线程同步方法汇总
    C#访问远程主机资源的方法
    Python实例---模拟微信网页登录(day1)
    github入门到上传本地项目
    Python学习--Selenium模块
    Python学习--打码平台
    Python学习--Selenium模块学习(2)
  • 原文地址:https://www.cnblogs.com/WR-Eternity/p/13741442.html
Copyright © 2011-2022 走看看