多项式对数函数 学习笔记 洛谷4725

题目链接

题意:
给出 n − 1 n-1 n1次多项式 A ( x ) A(x) A(x),求一个   m o d     x n \bmod{\:x^n} modxn下的多项式 B ( x ) B(x) B(x),满足 B ( x ) ≡ ln ⁡ A ( x ) ( m o d   x n ) B(x) \equiv \ln A(x)(mod\ x^n) B(x)lnA(x)(mod xn)
mod  998244353 \text{mod } 998244353 mod 998244353下进行。

题解:
好吧,我们需要用到一些微积分的知识。先介绍一下对于一个多项式,求导和积分后多项式会变成什么样子。

先介绍一下求导。对于一个多项式 f ( x ) = a 0 + a 1 x + a 2 x 2 + . . . + a n x n f(x)=a_0+a_1x+a_2x^2+...+a_nx^n f(x)=a0+a1x+a2x2+...+anxn,我们对其求导之后就会变成 f ′ ( x ) = a 1 + 2 a 2 x + 3 a 3 x 2 + . . . + n a n x n − 1 f'(x)=a_1+2a_2x+3a_3x^2+...+na_nx^{n-1} f(x)=a1+2a2x+3a3x2+...+nanxn1,也就是对于每一项,原来的指数乘到系数上,然后指数减一。

然后介绍一下积分。对于一个多项式 f ( x ) = a 0 + a 1 x + a 2 x 2 + . . . + a n − 1 x n − 1 f(x)=a_0+a_1x+a_2x^2+...+a_{n-1}x^{n-1} f(x)=a0+a1x+a2x2+...+an1xn1,我们对其积分之后就会变成 ∫ f ( x ) = a 0 1 x + a 1 2 x 2 + . . . + a n − 1 n x n + c \int f(x)=\frac{a_0}{1}x+\frac{a_1}{2}x^2+...+\frac{a_{n-1}}{n}x^n+c f(x)=1a0x+2a1x2+...+nan1xn+c,也就是对于第 i i i项,它的系数变为 a i − 1 i \frac{a_{i-1}}{i} iai1 + c +c +c是加上一个丢失的常数。

我们知道导数和积分可以看作逆运算,即 g ( x ) = ∫ g ′ ( x ) g(x)=\int g'(x) g(x)=g(x)。然后我们还要知道 ln ⁡ ′ ( x ) = 1 x \ln'(x)=\frac{1}{x} ln(x)=x1。然后对于一个复合函数 f ( g ( x ) ) f(g(x)) f(g(x)),它的导数 f ( g ( x ) ) ′ f(g(x))' f(g(x))的求导法则是 f ′ ( g ( x ) ) g ′ ( x ) f'(g(x))g'(x) f(g(x))g(x)

好,我们开始推式子。 ln ⁡ A ( x ) = ∫ ( ln ⁡ A ( x ) ) ′ = ∫ ( 1 A ( x ) A ′ ( x ) ) = ∫ A ′ ( x ) A ( x ) \ln A(x)=\int(\ln A(x))'=\int (\frac{1}{A(x)}A'(x))=\int \frac{A'(x)}{A(x)} lnA(x)=(lnA(x))=(A(x)1A(x))=A(x)A(x)

对于一个多项式,我们先求导再积分多项式不变,于是我们先求导,算出 A ′ ( x ) A'(x) A(x),其中的 1 A ( x ) \frac{1}{A(x)} A(x)1可以用多项式求逆来 O ( n l o g n ) O(nlogn) O(nlogn)的求出来,然后我们再积分回去就好了。其中知道了对多项式的求导和积分法则之后求导和积分都可以 O ( n ) O(n) O(n)完成,于是最后复杂度是 O ( n l o g n ) O(nlogn) O(nlogn)

代码:

#include <bits/stdc++.h>
using namespace std;

int n,m,l,rev[400010];
long long a[400010],b[400010],c[400010],d[400010],x[400010],y[400010];
const long long mod=998244353,g=3,gi=332748118;
inline int read()
{
	int x=0;
	char s=getchar();
	while(s>'9'||s<'0')
	s=getchar();
	while(s>='0'&&s<='9')
	{
		x=x*10+s-'0';
		s=getchar();
	}
	return x;
}
inline long long ksm(long long x,long long y)
{
	long long res=1;
	while(y)
	{
		if(y&1)
		res=res*x%mod;
		x=x*x%mod;
		y>>=1;
	}
	return res;
}
inline void ntt(long long *a,int dft,int len)
{
	m=len;
	l=0;
	for(len=1;len<m;len<<=1)
	++l;
	for(int i=0;i<len;++i)
	rev[i]=(rev[i>>1]>>1)|((i&1)<<(l-1));
	for(int i=0;i<len;++i)
	{
		if(i<rev[i])
		swap(a[i],a[rev[i]]);
	}
	for(int i=1;i<len;i<<=1)
	{
		long long wn=ksm((dft==1?g:gi),(mod-1)/(i<<1));
		for(int j=0,p=(i<<1);j<len;j+=p)
		{
			long long w=1;
			for(int k=0;k<i;++k)
			{
				long long xx=a[j+k],yy=w*a[i+j+k]%mod;
				a[j+k]=(xx+yy)%mod;
				a[i+j+k]=(xx-yy+mod)%mod;
				w=w*wn%mod;
			}
		}
	}
	if(dft==-1)
	{
		long long ni=ksm(m,mod-2);
		for(int i=0;i<len;++i)
		a[i]=a[i]*ni%mod;
	}
}
inline void inv(long long *a,long long *b,int len)
{
	if(len==1)
	{
		b[0]=ksm(a[0],mod-2);
		return;
	}
	inv(a,b,len>>1);
	for(int i=0;i<len;++i)
	{
		x[i]=a[i];
		y[i]=b[i];
	}
	ntt(x,1,len<<1);
	ntt(y,1,len<<1);
	for(int i=0;i<(len)<<1;++i)
	x[i]=x[i]*y[i]%mod*y[i]%mod;
	ntt(x,-1,len<<1);
	for(int i=0;i<len;++i)
	b[i]=(b[i]*2%mod-x[i]+mod)%mod;
	for(int i=0;i<(len<<1);++i)
	{
		x[i]=0;
		y[i]=0;
	}
}
int main()
{
	n=read();
	for(int i=0;i<=n-1;++i)
	a[i]=read();
	int ji; 
	for(ji=1;ji<=n;ji<<=1);
	for(int i=1;i<ji;++i)
	b[i-1]=a[i]*i%mod;
	b[ji-1]=0;
	inv(a,c,ji);				
	ntt(b,1,ji<<1);		
	ntt(c,1,ji<<1);			
	for(int i=0;i<(ji<<1);++i)
	b[i]=b[i]*c[i]%mod;	
	ntt(b,-1,ji<<1);
	for(int i=1;i<ji;++i)
	c[i]=b[i-1]*ksm(i,mod-2)%mod;
	c[0]=0;
	for(int i=0;i<n;++i)
	printf("%lld ",c[i]);
	printf("\n");
	return 0;
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值