把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu 4726 【模板】多项式指数函数(多项式 exp)

题面传送门
首先是牛顿迭代。
举个例子,你要求\(x^2-a=0\)并且你不会解一元二次方程。
然后你先找到一个\(x_0\)算出\(x=x_0\)的当前值。
然后求当前点\(x_0\)的切线,大概是\(y=f'(x_0)(x-x_0)+f(x_0)\)
带入\(y=0\)就可以解得\(x=x_0+\frac{f(x_0)}{f'(x_0)}\)
然后这样迭代下午精度就很高了。
这道题就是要求一个\(F(G(x))=\ln G(x)-A(x)=0\)
然后直接上牛顿迭代,假设我们现在是\(G_0(x)\),就有\(G(x)=G_0(x)+\frac{F(G_0(x))}{F'(G_0(x))}\)
这里\(F'(G_0(x))\)其实就是\(G_0(x)\)因为\(A\)是常数求导后没了。
所以这个式子相当于\(G(x)=(\ln G_0(x)-A(x)+1)G_0(x)\)
然后求个\(\ln\)就可以写了。时间复杂度\(O(nlogn)\)
code:

#include<bits/stdc++.h>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 300000
#define K 50
#define mod 998244353
#define Mod 998244352
#define eps (1e-4)
#define U unsigned int
#define it iterator
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (n*(x-1)+(y))
using namespace std;
int n;ll A[N+5],B[N+5];
I ll mpow(ll x,int y=mod-2){ll Ans=1;while(y) y&1&&(Ans=Ans*x%mod),y>>=1,x=x*x%mod;return Ans;}const int G=3,invG=mpow(G);
namespace Poly{
	int tr[N+5];ll C[N+5],D[N+5],k,F[N+5];I void Init(int n){k=1;while(k<2*n)k<<=1;for(RI i=0;i<k;i++) tr[i]=(tr[i>>1]>>1)|(i&1?k/2:0),D[i]=C[i]=0;}
	I void NTT(ll *A,int n,int flag){
		RI i,j,h;re ll key,now,pus;for(i=0;i<n;i++) i<tr[i]&&(swap(A[i],A[tr[i]]),0);for(i=2;i<=n;i<<=1){
			for(key=mpow(flag?G:invG,(mod-1)/i),j=0;j<n;j+=i){
				for(now=1,h=j;h<j+i/2;h++) pus=now*A[h+i/2]%mod,A[h+i/2]=(A[h]-pus+mod)%mod,A[h]=(A[h]+pus)%mod,now=now*key%mod;
			}
		}if(flag) return;ll invn=mpow(n);for(i=0;i<n;i++) A[i]=A[i]*invn%mod;
	}
	I void Get_Inv(ll *A,ll *B,int n){
		if(n==1){B[0]=mpow(A[0]);return;}Get_Inv(A,B,n+1>>1);RI i;Init(n);for(i=0;i<n;i++) C[i]=A[i],D[i]=B[i];NTT(C,k,1);NTT(D,k,1);for(i=0;i<k;i++) C[i]=(2-C[i]*D[i]%mod+mod)*D[i]%mod;for(NTT(C,k,0),i=0;i<n;i++) B[i]=C[i];
	}
	I void Get_Ln(ll *A,ll *B,int n){
		RI i;for(i=0;i<n;i++) B[i]=0;Get_Inv(A,B,n);Init(n);for(i=0;i<n;i++) C[i]=A[i+1]*(i+1)%mod,D[i]=B[i];NTT(C,k,1);NTT(D,k,1);for(i=0;i<k;i++) C[i]=C[i]*D[i]%mod;NTT(C,k,0);for(i=1;i<n;i++) B[i]=C[i-1]*mpow(i)%mod;B[0]=0; 
	}
	I void Get_Exp(ll *A,ll *B,int n){
		if(n==1){B[0]=1;return;}Get_Exp(A,B,n+1>>1);RI i;for(i=0;i<n;i++) F[i]=0;Get_Ln(B,F,n);Init(n);for(i=0;i<n;i++) D[i]=((!i)+A[i]-F[i]+mod)%mod,C[i]=B[i];NTT(C,k,1);NTT(D,k,1);for(i=0;i<k;i++) C[i]=C[i]*D[i]%mod;NTT(C,k,0);for(i=0;i<n;i++) B[i]=C[i];
	}
}
int main(){
	freopen("1.in","r",stdin);
	RI i;scanf("%d",&n);for(i=0;i<n;i++) scanf("%lld",&A[i]);for(Poly::Get_Inv(A,B,n),i=0;i<n;i++) printf("%lld ",B[i]);
}
posted @ 2021-08-30 20:16  275307894a  阅读(87)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end