多项式对数函数学习笔记

问题

现在给出一个 n n n 次多项式 A ( x ) A(x) A(x),其中它的常数项为 1 1 1,现在要求解 ln ⁡ A ( x ) \ln A(x) lnA(x)

前置知识

求导
现在有一个函数 f ( x ) f(x) f(x),对应着平面直角坐标系上的一条曲线。现在我们要求它在某处( x 0 x_0 x0)切线的斜率。显然斜率为 lim ⁡ x → x 0 f ( x ) − f ( x 0 ) x − x 0 \lim_{x\rightarrow x_0}\frac{f(x)-f(x_0)}{x-x_0} xx0limxx0f(x)f(x0)上式可以记作 f ′ ( x 0 ) = d f d x ( x 0 ) f'(x_0)=\frac{df}{dx}(x_0) f(x0)=dxdf(x0)其中的 d X dX dX 可以看成 Δ X \Delta X ΔX 趋近于零的结果。
称之为 f ( x ) f(x) f(x) x 0 x_0 x0 处的导数。暂时可以认为,在 f ( x ) f(x) f(x) 的定义域中任何一个 x 0 x_0 x0 处都对应着一个 f ′ ( x 0 ) f'(x_0) f(x0),因此所有的 f ′ ( x 0 ) f'(x_0) f(x0) 构成一个新的函数 f ′ ( x ) f'(x) f(x),称之为导函数,简称导数。我们称 f ′ ( x ) f'(x) f(x) f ( x ) f(x) f(x) 的导数, f ( x ) f(x) f(x) f ′ ( x ) f'(x) f(x) 的原函数。
下面给出几条对下面有用的公式
1. ( x k ) ′ = k x k − 1 (x^k)'=kx^{k-1} (xk)=kxk1,其中 k ≠ 0 k\not=0 k=0
2. ( ln ⁡ x ) ′ = 1 x (\ln x)'=\frac{1}{x} (lnx)=x1
3. [ a u ( x ) + b v ( x ) ] ′ = a u ′ ( x ) + b v ′ ( x ) [au(x)+bv(x)]'=au'(x)+bv'(x) [au(x)+bv(x)]=au(x)+bv(x)
4. u ′ [ v ( x ) ] = d u ( v ) d v d v ( x ) d x u'[v(x)]=\frac{du(v)}{dv}\frac{dv(x)}{dx} u[v(x)]=dvdu(v)dxdv(x)
事实上,第三条式子与第一条式子结合可以得到多项式函数的求导公式。
假设现在有一个多项式函数 f ( x ) = ∑ i = 0 n a i x i f(x)=\sum_{i=0}^na_ix^i f(x)=i=0naixi f ′ ( x ) = ∑ i = 1 n i a i x i − 1 f'(x)=\sum_{i=1}^{n}ia_ix^{i-1} f(x)=i=1niaixi1
不定积分
不定积分就是对于一个导数求其原函数的运算,记 f ( x ) = ∫ f ′ ( x ) d x f(x)=\int f'(x)dx f(x)=f(x)dx但一个导函数所对应的原函数不止一个,都可以写成由某个函数加上一个常数的形式,那个常数有时可以根据边界条件求得。

方法

要求 ln ⁡ A ( x ) \ln A(x) lnA(x),我们先把这个式子求导,得到 [ ln ⁡ A ( x ) ] ′ = d ln ⁡ A ( x ) d A ( x ) d A ( x ) d x = 1 A ( x ) A ′ ( x ) [\ln A(x)]'=\frac{d\ln A(x)}{dA(x)}\frac{dA(x)}{dx}=\frac{1}{A(x)}A'(x) [lnA(x)]=dA(x)dlnA(x)dxdA(x)=A(x)1A(x)再根据积分的定义,把它积分,就得到了 ln ⁡ A ( x ) = ∫ [ ln ⁡ A ( x ) ] ′ d x = ∫ A − 1 ( x ) A ′ ( x ) d x \ln A(x)=\int[\ln A(x)]'dx=\int A^{-1}(x)A'(x)dx lnA(x)=[lnA(x)]dx=A1(x)A(x)dx
这个式子表明先要把这个多项式求逆,再乘上原来多项式的导数,最后把它积分就行了。特殊的,由于 A ( x ) A(x) A(x) 常数项为 1 1 1,故取 ln ⁡ A ( x ) \ln A(x) lnA(x) 的常数项为 ln ⁡ 1 = 0 \ln 1=0 ln1=0

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
using namespace std;
ll mod=998244353,G[2]={332748118,3};
ll A[450001],invA[450001],f[450001],g[450001],inv;
int len,m,rev[450001];
ll qp(ll x,int y){
	if(y==0) return 1ll;
	if(y==1) return x;
	ll res=qp(x,y>>1);
	(res*=res)%=mod;
	if(y&1) (res*=x)%=mod;
	return res;
}
void NTT(ll *a,int flag,int n){
	ll w,w_n,x,y;
	for(int i=1;i<n;i+=1){
		if(i<rev[i]) swap(a[i],a[rev[i]]);
	}
	for(int i=1;i<n;i<<=1){
		w_n=qp(G[flag],(mod-1)/(i<<1));
		for(int j=0;j<n;j+=(i<<1)){
			w=1ll;
			for(int k=j;k<i+j;k+=1){
				x=a[k]; y=(a[k+i]*w)%mod;
				a[k]=(x+y)%mod;
				a[k+i]=(x-y+mod)%mod;
				(w*=w_n)%=mod;
			}
		}
	}
	if(!flag){
		inv=qp(n,mod-2);
		for(int i=0;i<n;i+=1) (a[i]*=inv)%=mod;
	}
	return;
}
int main(){
	int n;
	scanf("%d",&len); len-=1;
	for(int i=0;i<=len;i+=1) scanf("%lld",&A[i]);
	invA[0]=qp(A[0],mod-2);
	for(int i=1;i<=len;i<<=1){
		memset(g,0,sizeof(g)); m+=1;
		for(int j=0;j<i;j+=1) g[j]=invA[j];
		for(int j=0;j<(i<<1);j+=1) f[j]=A[j];
		for(int j=1;j<(i<<2);j+=1) rev[j]=((rev[j>>1]>>1)|((j&1)<<m));
		NTT(g,1,i<<2); NTT(f,1,i<<2);
		for(int j=0;j<(i<<2);j+=1) g[j]=(((g[j]*g[j])%mod)*f[j])%mod;
		NTT(g,0,i<<2);
		for(int j=i;j<(i<<1);j+=1) invA[j]=((invA[j]<<1)%mod-g[j]+mod)%mod;
	}  //A(x)求逆到invA(x)
	for(int i=0;i<len;i+=1){
		A[i]=(A[i+1]*(i+1)*1ll)%mod;  //A(x)求导到A(x)
	}
	m=1; while((1<<m)<=(len<<1)) m+=1; n=(1<<m);
	NTT(A,1,n); NTT(invA,1,n);
	for(int i=0;i<n;i+=1) (A[i]*=invA[i])%=mod;  //A'(x)*invA(x)
	NTT(A,0,n);
	printf("0 ");
	for(int i=1;i<=len;i+=1) printf("%lld ",(A[i-1]*qp(i,mod-2))%mod);  //积分得到ln A(x)
	printf("\n");
	return 0;
}

谢谢观看,记得点赞

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值