【xsy2978】Product of Roots 生成函数+多项式ln+多项式exp
题目大意:给你两个多项式f(x)和g(x),满足f(x)=n∏i=1(ai+1),g(x)=m∏i=1(bi+1)。
现在给你一个多项式h(x),满足h(x)=n∏i=1m∏j=1(aibj+1)
请输出多项式h的前k项,在模998244353意义下进行。
数据范围:n,m≤105。
我们现在有:
f(x)=n∏i=1(ai+1)
我们在等式两边都取对数,然后泰勒展开,得到:
ln(f(x))=n∑i=1ln(ai+1)=n∑i=1∞∑k=1(−1)k+1kxkaki
我们不难推出:
[xk]ln(f(x))=n∑i=1(−1)k+1kaki
g(x)同理。
我们现在来考虑h(x),我们现在有:
h(x)=n∏i=1m∏j=1(aibj+1)
和上面一样,我们在等式两边都取对数,然后泰勒展开,得到:
ln(h(x))=n∑i=1m∑j=1ln(aibj+1)=n∑i=1m∑j=1∞∑k=1(−1)k+1kxkakibkj=∞∑k=1xkn∑i=1(−1)k+1kakim∑i=1bki=∞∑k=1k(−1)k+1xkn∑i=1(−1)k+1kakim∑i=1(−1)k+1kbki
我们不难推出:
[xk]ln(h(x))=k(−1)k+1n∑i=1(−1)k+1kakim∑i=1(−1)k+1kbki=k(−1)k+1[xk]ln(f(x))[xk]ln(g(x))
我们可以考虑,用多项式求ln,求出ln(f(x))和ln(g(x)),然后求出ln(h(x))后再用多项式exp算回去,就得到多项式h了。
套一个多项式的板子就可以了。
完结撒花
1 #include<bits/stdc++.h> 2 #define M (1<<19) 3 #define L long long 4 #define MOD 998244353 5 #define G 3 6 using namespace std; 7 8 L pow_mod(L x,L k){ 9 L ans=1; 10 while(k){ 11 if(k&1) ans=ans*x%MOD; 12 x=x*x%MOD; k>>=1; 13 } 14 return ans; 15 } 16 17 void change(L a[],int n){ 18 for(int i=0,j=0;i<n-1;i++){ 19 if(i<j) swap(a[i],a[j]); 20 int k=n>>1; 21 while(j>=k) j-=k,k>>=1; 22 j+=k; 23 } 24 } 25 void NTT(L a[],int n,int on){ 26 change(a,n); 27 for(int h=2;h<=n;h<<=1){ 28 L wn=pow_mod(G,(MOD-1)/h); 29 for(int j=0;j<n;j+=h){ 30 L w=1; 31 for(int k=j;k<j+(h>>1);k++){ 32 L u=a[k],t=w*a[k+(h>>1)]%MOD; 33 a[k]=(u+t)%MOD; 34 a[k+(h>>1)]=(u-t+MOD)%MOD; 35 w=w*wn%MOD; 36 } 37 } 38 } 39 if(on==-1){ 40 L inv=pow_mod(n,MOD-2); 41 for(int i=0;i<n;i++) a[i]=a[i]*inv%MOD; 42 reverse(a+1,a+n); 43 } 44 } 45 46 void getinv(L a[],L b[],int n){ 47 if(n==1){b[0]=pow_mod(a[0],MOD-2); return;} 48 static L c[M],d[M]; 49 memset(c,0,n<<4); memset(d,0,n<<4); 50 getinv(a,c,n>>1); 51 for(int i=0;i<n;i++) d[i]=a[i]; 52 NTT(d,n<<1,1); NTT(c,n<<1,1); 53 for(int i=0;i<(n<<1);i++) b[i]=(2*c[i]-d[i]*c[i]%MOD*c[i]%MOD+MOD)%MOD; 54 NTT(b,n<<1,-1); 55 for(int i=0;i<n;i++) b[n+i]=0; 56 } 57 58 void qiudao(L a[],L b[],int n){ 59 memset(b,0,sizeof(b)); 60 for(int i=1;i<n;i++) b[i-1]=i*a[i]%MOD; 61 } 62 void jifen(L a[],L b[],int n){ 63 memset(b,0,sizeof(b)); 64 for(int i=0;i<n;i++) b[i+1]=a[i]*pow_mod(i+1,MOD-2)%MOD; 65 } 66 67 void getln(L a[],L b[],int n){ 68 static L c[M],d[M]; 69 memset(c,0,n<<4); memset(d,0,n<<4); 70 qiudao(a,c,n); getinv(a,d,n); 71 NTT(c,n<<1,1); NTT(d,n<<1,1); 72 for(int i=0;i<(n<<1);i++) c[i]=c[i]*d[i]%MOD; 73 NTT(c,n<<1,-1); 74 jifen(c,b,n); 75 } 76 77 void getexp(L a[],L b[],int n){ 78 if(n==1){b[0]=1; return;} 79 static L lnb[M]; memset(lnb,0,n<<4); 80 getexp(a,b,n>>1); getln(b,lnb,n); 81 for(int i=0;i<n;i++) lnb[i]=(a[i]-lnb[i]+MOD)%MOD,b[i+n]=0; 82 lnb[n]=0; 83 lnb[0]=(lnb[0]+1)%MOD; 84 NTT(lnb,n<<1,1); NTT(b,n<<1,1); 85 for(int i=0;i<(n<<1);i++) b[i]=b[i]*lnb[i]%MOD; 86 NTT(b,n<<1,-1); 87 for(int i=0;i<n;i++) b[i+n]=0; 88 } 89 90 int n,m,k,len; 91 L f[M]={0},g[M]={0},h[M]={0},lf[M]={0},lg[M]={0},lh[M]={0}; 92 93 int main(){ 94 scanf("%d%d%d",&n,&m,&k); 95 for(len=1;len<=(n+m+2);len<<=1); 96 for(int i=0;i<=n;i++) scanf("%lld",f+i); 97 for(int i=0;i<=m;i++) scanf("%lld",g+i); 98 getln(f,lf,len); 99 getln(g,lg,len); 100 for(int i=0;i<len;i++) lh[i]=(lf[i]*lg[i]%MOD*(i&1?i:-i)%MOD+MOD)%MOD; 101 getexp(lh,h,len); 102 for(int i=0;i<k;i++) printf("%lld ",h[i]); 103 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!