zoukankan      html  css  js  c++  java
  • 【洛谷4726】【模板】多项式指数函数(多项式 exp)

    点此看题面

    • 给定一个(n)次多项式(F(x)),求(G(x))满足(G(x)=e^{F(x)}(mod x^n))
    • (nle10^5),对(998244353)取模。

    牛顿迭代

    学习多项式(Exp)首先需要知道牛顿迭代

    实际上,牛顿迭代更常用于快速求一个数的平方根,这里也以此为例来介绍。

    考虑如果我们要求(lfloorsqrt a floor),就相当于求函数(f(x)=x^2-a)的近似零点。

    假设当前求出的近似值为(x_0),那么我们只要过((x_0,f(x_0)))作该图象的切线,然后取这条切线与(x)轴的交点作为新的(x_0),必然能得到一个更精确的近似值。(可以自行画图理解一下)

    方法已经知道了,至于实现,容易发现切线的解析式应该是:

    [y=f'(x_0)(x-x_0)+f(x_0) ]

    代入(y=0),然后把它变个形,便能解得:

    [x=x_0-frac{f(x_0)}{f'(x_0)} ]

    以上便是牛顿迭代用于快速求平方根的全部内容了。

    现在考虑推广,已知一个函数(A(x)),我们要求出一个函数(G(x))使得(A(G(x))=0)

    容易发现假设当前已经有一个近似函数(G_0(x)),便可以把它表示成一个与上面的式子近似的玩意儿:

    [G(x)=G_0(x)-frac{A(G_0(x))}{A'(G_0(x))} ]

    这就为我们求多项式(Exp)提供了思路。

    多项式(Exp)

    因为我们要求出(G(x))使得(G(x)=e^{F(x)}),所以就是要找到一个(G(x))使得:

    [A(G(x))=ln G(x)-F(x)=0 ]

    把它代入到前面求出的式子中得到:

    [G(x)=G_0(x)-frac{A(G_0(x))}{A'(G_0(x))} ]

    其中,(A'(G_0(x)))其实就是(ln' G_0(x)=frac1{G_0(x)}),因为(-F(x))可以视作常数项忽略掉。

    最终得到:

    [G(x)=G_0(x)-G_0(x)(ln G_0(x)-F(x))=G_0(x)(1-ln G_0(x)+F(x)) ]

    容易发现这只要递归做(O(logn))层即可。

    代码:(O(nlogn))

    #include<bits/stdc++.h>
    #define Tp template<typename Ty>
    #define Ts template<typename Ty,typename... Ar>
    #define Reg register
    #define RI Reg int
    #define Con const
    #define CI Con int&
    #define I inline
    #define W while
    #define N 100000
    #define X 998244353
    using namespace std;
    int n,a[N+5],b[N+5];
    I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
    class FastIO
    {
    	private:
    		#define FS 100000
    		#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
    		#define pc(c) (C==E&&(clear(),0),*C++=c)
    		#define D isdigit(c=tc())
    		int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
    	public:
    		I FastIO() {A=B=FI,E=(C=FO)+FS;}
    		Tp I void read(Ty& x) {x=0;W(!D);W(x=(x<<3)+(x<<1)+(c&15),D);}
    		Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);pc(' ');}
    		I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
    }F;
    namespace Poly//多项式
    {
    	#define Init(n) P=1,L=0;W(P<=2*(n)) P<<=1,++L;
    		for(i=0;i^P;++i) A[i]=B[i]=0,R[i]=((R[i>>1]>>1)|((i&1)<<L-1));//预处理n次多项式的乘法
    	int PR=3,P,L,R[N<<2],p[N+5],A[N<<2],B[N<<2];
    	I void NTT(int* s,CI op)//NTT
    	{
    		RI i,j,k,x,y,U,S;for(i=0;i^P;++i) i<R[i]&&(x=s[i],s[i]=s[R[i]],s[R[i]]=x);
    		for(i=1;i^P;i<<=1) for(U=QP(QP(PR,op),(X-1)/(i<<1)),j=0;j^P;j+=i<<1) for(S=1,k=0;
    			k^i;++k,S=1LL*S*U%X) s[j+k]=((x=s[j+k])+(y=1LL*S*s[i+j+k]%X))%X,s[i+j+k]=(x-y+X)%X;
    	}
    	I void Inv(CI n,int* a,int* b)//多项式求逆
    	{
    		if(!n) return (void)(b[0]=QP(a[0],X-2));RI i;Inv(n>>1,a,b);
    		Init(n);for(i=0;i<=n;++i) A[i]=a[i],B[i]=b[i];
    		for(NTT(A,1),NTT(B,1),i=0;i^P;++i) A[i]=(2LL*B[i]-1LL*A[i]*B[i]%X*B[i]%X+X)%X;
    		RI t=QP(P,X-2);for(NTT(A,X-2),i=0;i<=n;++i) b[i]=1LL*A[i]*t%X;
    	}
    	I void Ln(CI n,int* a,int* b)//多项式ln
    	{
    		RI i;for(i=0;i<=n;++i) b[i]=0;Inv(n,a,b);
    		Init(n-1);for(i=0;i<=n-1;++i) A[i]=1LL*a[i+1]*(i+1)%X,B[i]=b[i];
    		for(NTT(A,1),NTT(B,1),i=0;i^P;++i) A[i]=1LL*A[i]*B[i]%X;
    		RI t=QP(P,X-2);for(NTT(A,X-2),b[0]=i=0;i^n;++i) b[i+1]=1LL*A[i]*t%X*QP(i+1,X-2)%X;
    	}
    	int q[N+5];I void Exp(CI n,int* a,int* b)//多项式Exp
    	{
    		if(!n) return (void)(b[0]=1);RI i;Exp(n>>1,a,b);//边界
    		Ln(n,b,p),Init(n);for(i=0;i<=n;++i) A[i]=b[i],B[i]=(!i-p[i]+a[i]+X)%X;//搞出两个多项式
    		for(NTT(A,1),NTT(B,1),i=0;i^P;++i) A[i]=1LL*A[i]*B[i]%X;//卷积
    		RI t=QP(P,X-2);for(NTT(A,X-2),i=0;i<=n;++i) b[i]=1LL*A[i]*t%X;//还原
    	}
    }
    int main()
    {
    	RI i;for(F.read(n),--n,i=0;i<=n;++i) F.read(a[i]);//读入,方便起见将n减1
    	for(Poly::Exp(n,a,b),i=0;i<=n;++i) F.write(b[i]);return F.clear(),0;//输出
    }
    
    败得义无反顾,弱得一无是处
  • 相关阅读:
    ovx openVirtex的阅读文档
    如何通过修改文件添加用户到sudoers上
    服务器上搭建flowvisor平台
    flowvisor连接ovs
    ovs的学习
    新手报道
    Java——枚举类(疯狂Java讲义6.9)
    Java——Lambda表达式
    Java——foreach的使用
    Java:成员变量、局部变量和静态变量
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/PolyExp.html
Copyright © 2011-2022 走看看