【XSY2978】Product of Roots(多项式)

题面&题意

Product of Roots

已知 f ( x ) , g ( x ) , h ( x ) f(x),g(x),h(x) f(x),g(x),h(x) 能表示成:

f ( x ) = ∏ i = 1 n ( a i x + 1 ) g ( x ) = ∏ i = 1 m ( b i x + 1 ) h ( x ) = ∏ i = 1 n ∏ j = 1 m ( a i b j x + 1 ) \begin{aligned} f(x)&=\prod_{i=1}^n(a_ix+1)\\ g(x)&=\prod_{i=1}^m(b_ix+1)\\ h(x)&=\prod_{i=1}^n\prod_{j=1}^m(a_ib_jx+1) \end{aligned} f(x)g(x)h(x)=i=1n(aix+1)=i=1m(bix+1)=i=1nj=1m(aibjx+1)

现在给你 f ( x ) f(x) f(x) g ( x ) g(x) g(x),要求 h ( x ) h(x) h(x)

n , m ≤ 1 0 5 , k ≤ min ⁡ ( 1 0 5 , n m + 1 ) n,m\leq 10^5,k\leq \min(10^5,nm+1) n,m105,kmin(105,nm+1)

题解

考虑取对数然后泰勒展开,设 l i ( x ) = ln ⁡ ( a i x + 1 ) l_i(x)=\ln(a_ix+1) li(x)=ln(aix+1)

ln ⁡ ( f ( x ) ) = ∑ i = 1 n ln ⁡ ( a i x + 1 ) = ∑ i = 1 n l i ( x ) = ∑ i = 1 n ∑ k = 0 ∞ l i ( k ) ( 0 ) k ! x k \begin{aligned} \ln\big(f(x)\big)&=\sum_{i=1}^n\ln(a_ix+1)=\sum_{i=1}^nl_i(x)\\ &=\sum_{i=1}^n\sum_{k=0}^{\infty}\dfrac{l_i^{(k)}(0)}{k!}x^k\\ \end{aligned} ln(f(x))=i=1nln(aix+1)=i=1nli(x)=i=1nk=0k!li(k)(0)xk

引理: l i ( n ) ( x ) = [ ln ⁡ ( a i x + 1 ) ] ( n ) = ( − 1 ) n − 1 ( n − 1 ) ! a i n ( a i x + 1 ) − n l_i^{(n)}(x)=\big[\ln(a_ix+1)\big]^{(n)}=(-1)^{n-1}(n-1)!a_i^n(a_ix+1)^{-n} li(n)(x)=[ln(aix+1)](n)=(1)n1(n1)!ain(aix+1)n n > 0 n>0 n>0)。

证明:

考虑归纳证明。

首先当 n = 1 n=1 n=1 时, [ ln ⁡ ( a i x + 1 ) ] ′ = ln ⁡ ′ ( a i x + 1 ) ⋅ ( a i x + 1 ) ′ = 1 a i x + 1 ⋅ a = a i ( a i x + 1 ) − 1 \big[\ln(a_ix+1)\big]'=\ln'(a_ix+1)\cdot\big(a_ix+1\big)'=\dfrac{1}{a_ix+1}\cdot a=a_i(a_ix+1)^{-1} [ln(aix+1)]=ln(aix+1)(aix+1)=aix+11a=ai(aix+1)1

考虑由 l i ( n ) ( x ) l_i^{(n)}(x) li(n)(x) l i ( n + 1 ) ( x ) l_i^{(n+1)}(x) li(n+1)(x) 推导:

s ( x ) = ( − 1 ) n − 1 ( n − 1 ) ! a i n x − n s(x)=(-1)^{n-1}(n-1)!a_i^nx^{-n} s(x)=(1)n1(n1)!ainxn t ( x ) = a i x + 1 t(x)=a_ix+1 t(x)=aix+1,那么 s ′ ( x ) = ( − 1 ) n n ! a i n x − ( n + 1 ) s'(x)=(-1)^nn!a_i^nx^{-(n+1)} s(x)=(1)nn!ainx(n+1) t ′ ( x ) = a i t'(x)=a_i t(x)=ai

则:

l i ( n + 1 ) ( x ) = [ l i ( n ) ( x ) ] ′ = [ s ( t ( x ) ) ] ′ = s ′ ( t ( x ) ) t ′ ( x ) = ( − 1 ) n n ! a i n ( a i x + 1 ) − ( n + 1 ) ⋅ a i = ( − 1 ) n n ! a i n + 1 ( a i x + 1 ) − ( n + 1 ) \begin{aligned} l_i^{(n+1)}(x)&=\left[l_i^{(n)}(x)\right]'\\ &=\bigg[s\big(t(x)\big)\bigg]'=s'\big(t(x)\big)t'(x)\\ &=(-1)^nn!a_i^n(a_ix+1)^{-(n+1)}\cdot a_i\\ &=(-1)^nn!a_i^{n+1}(a_ix+1)^{-(n+1)} \end{aligned} li(n+1)(x)=[li(n)(x)]=[s(t(x))]=s(t(x))t(x)=(1)nn!ain(aix+1)(n+1)ai=(1)nn!ain+1(aix+1)(n+1)

证毕。

代入得:

ln ⁡ ( f ( x ) ) = ∑ i = 1 n ∑ k = 0 ∞ l i ( k ) ( 0 ) k ! x k = ∑ i = 1 n ∑ k = 0 ∞ ( − 1 ) k − 1 ( k − 1 ) ! a i k ( a i × 0 + 1 ) − k k ! x k = ∑ i = 1 n ∑ k = 0 ∞ ( − 1 ) k − 1 k a i k x k \begin{aligned} \ln\big(f(x)\big) &=\sum_{i=1}^n\sum_{k=0}^{\infty}\dfrac{l_i^{(k)}(0)}{k!}x^k\\ &=\sum_{i=1}^n\sum_{k=0}^{\infty}\dfrac{(-1)^{k-1}(k-1)!a_i^k(a_i\times 0+1)^{-k}}{k!}x^k\\ &=\sum_{i=1}^n\sum_{k=0}^{\infty}\dfrac{(-1)^{k-1}}{k}a_i^kx^k\\ \end{aligned} ln(f(x))=i=1nk=0k!li(k)(0)xk=i=1nk=0k!(1)k1(k1)!aik(ai×0+1)kxk=i=1nk=0k(1)k1aikxk

那么易得:

[ x k ] ln ⁡ ( f ( x ) ) = ∑ i = 1 n ( − 1 ) k − 1 k a i k [x^k]\ln\big(f(x)\big)=\sum_{i=1}^n\dfrac{(-1)^{k-1}}{k}a_i^k [xk]ln(f(x))=i=1nk(1)k1aik

g ( x ) g(x) g(x) 同理。

同样地,我们对 h ( x ) h(x) h(x) 也取对数:

ln ⁡ ( h ( x ) ) = ∑ i = 1 n ∑ j = 1 m ln ⁡ ( a i b j x + 1 ) \ln\big(h(x)\big)=\sum_{i=1}^n\sum_{j=1}^m\ln(a_ib_jx+1) ln(h(x))=i=1nj=1mln(aibjx+1)

注意到 ln ⁡ ( a i b j x + 1 ) \ln(a_ib_jx+1) ln(aibjx+1) ln ⁡ ( a i x + 1 ) \ln(a_ix+1) ln(aix+1) 形式上是相似的,所以我们也同理地得到:

ln ⁡ ( h ( x ) ) = ∑ i = 1 n ∑ j = 1 m ln ⁡ ( a i b j x + 1 ) = ∑ i = 1 n ∑ j = 1 m ∑ k = 0 ∞ ( − 1 ) k − 1 k ( a i b j ) k x k \begin{aligned} \ln\big(h(x)\big)&=\sum_{i=1}^n\sum_{j=1}^m\ln(a_ib_jx+1)\\ &=\sum_{i=1}^n\sum_{j=1}^m\sum_{k=0}^{\infty}\dfrac{(-1)^{k-1}}{k}(a_ib_j)^kx^k \end{aligned} ln(h(x))=i=1nj=1mln(aibjx+1)=i=1nj=1mk=0k(1)k1(aibj)kxk

考虑往 f ( x ) f(x) f(x) g ( x ) g(x) g(x) 的方向凑:

ln ⁡ ( h ( x ) ) = ∑ i = 1 n ∑ j = 1 m ∑ k = 0 ∞ ( − 1 ) k − 1 k ( a i b j ) k x k = ∑ k = 0 ∞ ( − 1 ) k − 1 k x k ∑ i = 1 n a i k ∑ j = 1 m b j k = ∑ k = 0 ∞ k ( − 1 ) k − 1 x k ∑ i = 1 n ( − 1 ) k − 1 k a i k ∑ j = 1 m ( − 1 ) k − 1 k b j k \begin{aligned} \ln\big(h(x)\big) &=\sum_{i=1}^n\sum_{j=1}^m\sum_{k=0}^{\infty}\dfrac{(-1)^{k-1}}{k}(a_ib_j)^kx^k\\ &=\sum_{k=0}^{\infty}\dfrac{(-1)^{k-1}}{k}x^k\sum_{i=1}^na_i^k\sum_{j=1}^mb_j^k\\ &=\sum_{k=0}^{\infty}\dfrac{k}{(-1)^{k-1}}x^k\sum_{i=1}^n\dfrac{(-1)^{k-1}}{k}a_i^k\sum_{j=1}^m\dfrac{(-1)^{k-1}}{k}b_j^k \end{aligned} ln(h(x))=i=1nj=1mk=0k(1)k1(aibj)kxk=k=0k(1)k1xki=1naikj=1mbjk=k=0(1)k1kxki=1nk(1)k1aikj=1mk(1)k1bjk

那么:

[ x k ] ln ⁡ ( h ( x ) ) = k ( − 1 ) k − 1 ∑ i = 1 n ( − 1 ) k − 1 k a i k ∑ j = 1 m ( − 1 ) k − 1 k b j k = k ( − 1 ) k − 1 ( [ x k ] ln ⁡ ( f ( x ) ) ) ( [ x k ] ln ⁡ ( g ( x ) ) ) \begin{aligned} \left[x^k\right]\ln(h(x))&=\dfrac{k}{(-1)^{k-1}}\sum_{i=1}^n\dfrac{(-1)^{k-1}}{k}a_i^k\sum_{j=1}^m\dfrac{(-1)^{k-1}}{k}b_j^k\\ &=\dfrac{k}{(-1)^{k-1}}\bigg([x^k]\ln\big(f(x)\big)\bigg)\bigg([x^k]\ln\big(g(x)\big)\bigg) \end{aligned} [xk]ln(h(x))=(1)k1ki=1nk(1)k1aikj=1mk(1)k1bjk=(1)k1k([xk]ln(f(x)))([xk]ln(g(x)))

那么我们可以先通过 ln ⁡ ( f ( x ) ) \ln\big(f(x)\big) ln(f(x)) ln ⁡ ( g ( x ) ) \ln\big(g(x)\big) ln(g(x)) 求出 ln ⁡ ( h ( x ) ) \ln\big(h(x)\big) ln(h(x)),然后再求 exp ⁡ \exp exp 就可以求出 h ( x ) h(x) h(x) 了。

代码如下:

#include<bits/stdc++.h>

#define LN 19
#define N 100010

using namespace std;

namespace modular
{
	const int mod=998244353;
	inline int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
	inline int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
	inline int mul(int x,int y){return 1ll*x*y%mod;}
}using namespace modular;

inline int read()
{
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9')
	{
		if(ch=='-') f=-1;
		ch=getchar();
	}
	while(ch>='0'&&ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^'0');
		ch=getchar();
	}
	return x*f;
}

inline int poww(int a,int b)
{
	int ans=1;
	while(b)
	{
		if(b&1) ans=mul(ans,a);
		a=mul(a,a);
		b>>=1;
	}
	return ans;
}

int n,m,k;
int inv[N<<2];
int rev[N<<2],w[LN][N<<2][2];
int f[N<<2],g[N<<2],h[N<<2];
int lnf[N<<2],lng[N<<2],lnh[N<<2];

void init(int limit)
{
	for(int i=0;i<limit;i++) inv[i]=poww(i,mod-2);
	for(int bit=0,mid=1;mid<limit;bit++,mid<<=1)
	{
		int len=mid<<1;
		int gn=poww(3,(mod-1)/len);
		int ign=poww(gn,mod-2);
		int g=1,ig=1;
		for(int j=0;j<mid;g=mul(g,gn),ig=mul(ig,ign),j++)
			w[bit][j][0]=g,w[bit][j][1]=ig;
	}
}

void NTT(int *a,int limit,int opt)
{
	opt=(opt<0);
	for(int i=0;i<limit;i++) rev[i]=(rev[i>>1]>>1)|((i&1)*(limit>>1));
	for(int i=0;i<limit;i++) if(i<rev[i]) swap(a[i],a[rev[i]]);
	for(int bit=0,mid=1;mid<limit;bit++,mid<<=1)
	{
		for(int i=0,len=mid<<1;i<limit;i+=len)
		{
			for(int j=0;j<mid;j++)
			{
				int x=a[i+j],y=mul(w[bit][j][opt],a[i+mid+j]);
				a[i+j]=add(x,y),a[i+mid+j]=dec(x,y);
			}
		}
	}
	if(opt)
	{
		int tmp=poww(limit,mod-2);
		for(int i=0;i<limit;i++)
			a[i]=mul(a[i],tmp);
	}
}

void getdao(int *f,int *g,int n)
{
	for(int i=1;i<n;i++)
		g[i-1]=mul(i,f[i]);
	g[n-1]=0;
}

void getint(int *f,int *g,int n)
{
	for(int i=n-1;i>=1;i--)
		g[i]=mul(inv[i],f[i-1]);
	g[0]=0;
}

void getinv(int *f,int *g,int n)
{
	static int ff[N<<2];
	g[0]=poww(f[0],mod-2);
	int now=2;
	for(;now<(n<<1);now<<=1)
	{
		int limit=now<<1;
		for(int i=0;i<now;i++) ff[i]=f[i];
		NTT(ff,limit,1),NTT(g,limit,1);
		for(int i=0;i<limit;i++)
			g[i]=mul(dec(2,mul(ff[i],g[i])),g[i]);
		NTT(g,limit,-1);
		for(int i=now;i<limit;i++) g[i]=0;
	}
	for(int i=n;i<now;i++) g[i]=0;
	for(int i=0;i<now;i++) ff[i]=0;
}

void getln(int *f,int *g,int n)
{
	static int daof[N<<2],invf[N<<2],daog[N<<2];
	getdao(f,daof,n);
	getinv(f,invf,n);
	int limit=1;
	while(limit<(n<<1)) limit<<=1;
	NTT(daof,limit,1),NTT(invf,limit,1);
	for(int i=0;i<limit;i++) daog[i]=mul(daof[i],invf[i]);
	NTT(daog,limit,-1);
	getint(daog,g,n);
	for(int i=0;i<limit;i++) daof[i]=invf[i]=daog[i]=0;
}

void getexp(int *f,int *g,int n)
{
	static int lng[N<<2],ff[N<<2];
	g[0]=1;
	int now=2;
	for(;now<(n<<1);now<<=1)
	{
		int limit=now<<1;
		getln(g,lng,now);
		for(int i=0;i<now;i++) ff[i]=dec(f[i],lng[i]);
		ff[0]=add(ff[0],1);
		NTT(g,limit,1),NTT(ff,limit,1);
		for(int i=0;i<limit;i++) g[i]=mul(g[i],ff[i]);
		NTT(g,limit,-1);
		for(int i=now;i<limit;i++) g[i]=0;
	}
	for(int i=n;i<now;i++) g[i]=0;
	for(int i=0;i<now;i++) lng[i]=ff[i]=0;
}

int main()
{
	n=read()+1,m=read()+1,k=read();
	int limit=1;
	while(limit<(k<<1)) limit<<=1;
	init(limit);
	for(int i=0;i<n;i++) f[i]=read();
	for(int i=0;i<m;i++) g[i]=read();
	getln(f,lnf,k),getln(g,lng,k);
	for(int i=0;i<k;i++)
	{
		lnh[i]=mul(i,mul(lnf[i],lng[i]));
		if(!(i&1)) lnh[i]=dec(0,lnh[i]);
	}
	getexp(lnh,h,k);
	for(int i=0;i<k;i++)
		printf("%d ",h[i]);
	return 0;
}
/*
2 2 5
1 2 1
1 2 1
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值