一道多项式exp模板题

多项式什么的真难写QwQ
题目大意:已知:
f ( x ) = ∏ i = 1 n ( 1 + a i x ) g ( x ) = ∏ i = 1 m ( 1 + b i x ) h ( x ) = ∏ i = 1 n ∏ j = 1 m ( 1 + a i b j x ) f(x)=\prod_{i=1}^n(1+a_ix)\\g(x)=\prod_{i=1}^m(1+b_ix)\\h(x)=\prod_{i=1}^n\prod_{j=1}^m(1+a_ib_jx) f(x)=i=1n(1+aix)g(x)=i=1m(1+bix)h(x)=i=1nj=1m(1+aibjx)
给定 f ( x ) = ∑ i = 0 n f i x i ,   g ( x ) = ∑ i = 0 m g i x i f(x)=\sum_{i=0}^n f_ix^i,\ g(x)=\sum_{i=0}^m g_ix^i f(x)=i=0nfixi, g(x)=i=0mgixi,求h的前k项,1e5。

对f,g和h取ln:
l n f ( x ) = ∑ k > 0 ( − 1 ) k − 1 k x k ( ∑ i = 1 n a i k ) = ∑ k > 0 ( − 1 ) k − 1 k x k S k ( a ) \mathrm{ln}f(x)=\sum_{k>0}\frac{(-1)^{k-1}}{k}x^k(\sum_{i=1}^na_i^k)\\=\sum_{k>0}\frac{(-1)^{k-1}}{k}x^kS_k(a) lnf(x)=k>0k(1)k1xk(i=1naik)=k>0k(1)k1xkSk(a)
其中S_k(a)表示a的k次方和。
l n h ( x ) = ∑ k > 0 ( − 1 ) k − 1 k x k ( ∑ i = 1 n a i k ) ( ∑ i = 1 m b i k ) = ∑ k > 0 ( − 1 ) k − 1 k x k S k ( a ) S k ( b ) \mathrm{ln}h(x)=\sum_{k>0}\frac{(-1)^{k-1}}{k}x^k(\sum_{i=1}^na_i^k)(\sum_{i=1}^mb_i^k)\\=\sum_{k>0}\frac{(-1)^{k-1}}{k}x^kS_k(a)S_k(b) lnh(x)=k>0k(1)k1xk(i=1naik)(i=1mbik)=k>0k(1)k1xkSk(a)Sk(b)
因此先对f和g求ln,可以得到S_k(a)和S_k(b),这样可以得到ln(h),然后做一次exp即可。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define gc getchar()
#define N 1600010
#define p 998244353
#define lint long long
#define clr(a,n) memset(a,0,sizeof(int)*(n))
#define cpy(a,b,n) memcpy(a,b,sizeof(int)*(n))
#define debug(x) cerr<<#x<<"="<<x
#define sp <<" "
#define ln <<endl
using namespace std;
inline int inn()
{
	int x,ch;while((ch=gc)<'0'||ch>'9');
	x=ch^'0';while((ch=gc)>='0'&&ch<='9')
		x=(x<<1)+(x<<3)+(ch^'0');return x;
}
int e[N],h[N],t[N],r[N],A1[N],A2[N],f[N],g[N],fln[N],gln[N],hln[N],ans[N];
inline int fast_pow(int x,int k,int ans=1)
{	for(;k;k>>=1,x=(lint)x*x%p) (k&1)?ans=(lint)ans*x%p:0;return ans;	}
inline int NTT(int *a,int n,int s)
{
	for(int i=1;i<n;i++) if(i<r[i]) swap(a[i],a[r[i]]);
	for(int i=2;i<=n;i<<=1)
	{
		int wn=fast_pow(3,(s>0)?(p-1)/i:p-1-(p-1)/i);
		for(int j=0,t=i>>1;j<n;j+=i)
			for(int k=0,w=1;k<t;k++,w=(lint)w*wn%p)
			{
				int x=a[j+k],y=(lint)w*a[j+k+t]%p;
				a[j+k]=(x+y)%p,a[j+k+t]=(x-y+p)%p;
			}
	}
	int ninv=fast_pow(n,p-2);
	if(s<0) for(int i=0;i<n;i++) a[i]=(lint)a[i]*ninv%p;
	return 0;
}
inline int tms(int *a,int *b,int *c,int n,int m)//c=ab,a[n]=b[m]=0
{
	int k=1,L=0;while(k<n+m) k<<=1,L++;
	for(int i=1;i<k;i++) r[i]=(r[i>>1]>>1)|((i&1)<<(L-1));
	clr(A1,k),cpy(A1,a,n),NTT(A1,k,1),
	clr(A2,k),cpy(A2,b,m),NTT(A2,k,1);
	for(int i=0;i<k;i++) c[i]=(lint)A1[i]*A2[i]%p;
	return NTT(c,k,-1);
}
inline int tms(int *a,int *b,int *c,int n) { return tms(a,b,c,n,n); }
inline int polyinv(int *a,int *inv,int m)
{
	int n=1;while(n<=m) n<<=1;
	clr(inv,n),inv[0]=fast_pow(a[0],p-2);
	for(int i=2;i<=n;i<<=1)
	{
		cpy(h,inv,i);for(int j=0;j<i;j++) h[j]=2ll*h[j]%p;
		tms(inv,inv,inv,i>>1),tms(inv,a,inv,i);
		for(int j=0;j<i;j++) inv[j]=(h[j]-inv[j]+p)%p;
		clr(inv+i,i);
	}
	return 0;
}
inline int polydif(int *a,int *b,int n)
{
	b[n]=0;for(int i=0;i<n;i++) b[i]=(i+1ll)*a[i+1]%p;return 0;
}
inline int polyint(int *a,int *b,int n)
{
	b[0]=0;for(int i=1;i<=n;i++) b[i]=(lint)a[i-1]*fast_pow(i,p-2)%p;return 0;
}
inline int polyln(int *a,int *pln,int n)
{
	return polyinv(a,pln,n),polydif(a,h,n),tms(pln,h,h,n),polyint(h,pln,n);
}
inline int polyexp(int *a,int *e,int m)
{
	int n=1;while(n<=m*2) n<<=1;clr(e,n),e[0]=1;
	for(int i=2;i<=n;i<<=1)
	{
		polyln(e,t,i>>1);
		for(int j=0;j<(i>>1);j++) t[j]=(a[j]-t[j]+(j==0)+p)%p;
		tms(e,t,e,i>>1),clr(e+i,i);
	}
	return 0;
}
inline int sol(int x,int s) { return (s&1)?(p-x)%p:x; }
inline int get_s(int *fln,int *f,int n)
{
	for(int i=1;i<=n;i++) f[i]=sol((lint)i*fln[i]%p,i-1);return 0;
}
inline int get_hln(int *f,int *g,int *hln,int n)
{
	for(int i=1;i<=n;i++) hln[i]=sol((lint)f[i]*g[i]%p,i-1);
	for(int i=1;i<=n;i++) hln[i]=(lint)hln[i]*fast_pow(i,p-2)%p;
	return 0;
}
int main()
{
	int n=inn(),m=inn(),k=inn();
	for(int i=0;i<=n;i++) f[i]=inn();
	for(int i=0;i<=m;i++) g[i]=inn();
	polyln(f,fln,k),polyln(g,gln,k);
	get_s(fln,f,k),get_s(gln,g,k);
	get_hln(f,g,hln,k),polyexp(hln,ans,k);
	for(int i=0;i<k;i++) printf("%d ",ans[i]);
	return !printf("\n");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值