通过二项式,可以得出:
bk=∑ni=0ci∗Cki∗biasn−i
bk=∑ni=0ci∗i!k!∗(i−k)!∗biasn−i
k!∗bk=∑ni=0(ci∗i!)∗biasi−k(i−k)!
看上去可以用FFT快速计算k!∗bk
建立两个数组
Ai=ci∗i!
Bi=biasn−i(n−i)!
i>n时,Ai=Bi=0
可以得到
k!∗bk=∑k+ni=0Ai∗Bk+n−i
然后卷积一下就好了。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1<<18;
const long long mod=998244353;
const int G=3;
long long rev[MAXN],w[2][MAXN];
long long fac[MAXN],inv[MAXN];
long long A[MAXN],B[MAXN];
long long pw[MAXN],ipw[MAXN];
long long c[MAXN],ans[MAXN];
int n;
long long powmod(long long x,long long p)
{
long long ret=1;
while(p)
{
if(p&1)
ret=ret*x%mod;
x=x*x%mod;
p>>=1;
}
return ret;
}
void init()
{
fac[0]=1;
for(int i=1;i<MAXN;i++)
fac[i]=fac[i-1]*i%mod;
inv[MAXN-1]=powmod(fac[MAXN-1],mod-2);
for(int i=MAXN-2;i>=0;i--)
inv[i]=inv[i+1]*(i+1)%mod;
}
void initfft(int n)
{
int i,k,x,y,v,dv;
for(i=0;i<=n-1;i++)
{
x=i;
y=0;
for(k=1;k<n;k<<=1,x>>=1)
{
(y<<=1)|=(x&1);
}
rev[i]=y;
}
v=powmod(G,(mod-1)/n);
dv=powmod(v,mod-2);
w[0][0]=w[1][0]=1;
for(i=1;i<=n-1;i++)
{
w[0][i]=w[0][i-1]*v%mod;
w[1][i]=w[1][i-1]*dv%mod;
}
}
inline void fft(long long *A,int n,int ff)
{
int i,j,k,t,l,v,x,y;
for(i=0;i<=n-1;i++)
{
if(i<rev[i])
swap(A[i],A[rev[i]]);
}
for(i=1;i<n;i<<=1)
{
for(j=0,t=n/(i<<1);j<n;j+=(i<<1))
{
for(k=0,l=0;k<i;k++,l+=t)
{
x=A[i+j+k]*w[ff][l]%mod;
y=A[j+k];
A[j+k]=(x+y)%mod;
A[i+j+k]=(y+mod-x)%mod;
}
}
}
if(ff)
{
v=powmod(n,mod-2);
for(i=0;i<=n-1;i++)
A[i]=A[i]*v%mod;
}
}
void move(long long *f,int bias,long long *g)
{
int i,inv_bias,m;
if(bias==0)
{
for(i=0;i<=n;i++)
g[i]=f[i];
return;
}
bias=(mod-bias)%mod;
pw[0]=1;//pw[i]表示bias的i次方
for(i=1;i<=n;i++)
pw[i]=pw[i-1]*bias%mod;
ipw[0]=1;//ipw[i]表示bias的-i次方
inv_bias=powmod(bias,mod-2);
for(i=1;i<=n;i++)
ipw[i]=ipw[i-1]*inv_bias%mod;
m=1;
while(m<=2*n+2)//设置m为2的整次幂
m<<=1;
for(i=0;i<=m-1;i++)
A[i]=B[i]=0;
initfft(m);//初始化权值
for(i=0;i<=n;i++)
A[i]=f[i]*fac[i]%mod;
for(i=0;i<=n;i++)
B[n-i]=pw[i]*inv[i]%mod;
fft(A,m,0);//正变换
fft(B,m,0);
for(i=0;i<=m-1;i++)//卷积
A[i]=A[i]*B[i]%mod;
fft(A,m,1);//逆变换
for(i=0;i<=n;i++)
g[i]=A[i+n]*inv[i]%mod;
}
int main()
{
long long i,m,x,bias;
init();
while(~scanf("%d",&n))
{
for(i=0;i<=n;i++)
scanf("%lld",&c[i]);
bias=0;
scanf("%lld",&m);
for(i=1;i<=m;i++)
{
scanf("%lld",&x);
bias=(bias+x)%mod;
}
move(c,bias,ans);
for(i=0;i<=n;i++)
printf("%lld ",ans[i]);
puts("");
}
}