思路:
设
s
u
m
=
−
∑
a
i
sum = -\sum a_i
sum=−∑ai
故对于最终函数的第
k
k
k项,有:
A
n
s
k
=
∑
i
=
k
n
c
i
C
i
k
(
−
s
u
m
)
i
−
k
Ans_k = \sum_{i=k}^nc_iC_{i}^{k}(-sum)^{i-k}
Ansk=i=k∑nciCik(−sum)i−k
将组合数展开:
A
n
s
k
=
∑
i
=
k
n
c
i
(
−
s
u
m
)
i
−
k
i
!
k
!
(
i
−
k
)
!
Ans_k = \sum_{i=k}^nc_i(-sum)^{i-k}\frac{i!}{k!(i-k)!}
Ansk=i=k∑nci(−sum)i−kk!(i−k)!i!
记
A
[
i
]
=
c
i
i
!
B
[
i
]
=
(
−
A
)
i
i
!
A[i] = c_ii! \space B[i] = \frac{(-A)^i}{i!}
A[i]=cii! B[i]=i!(−A)i
则:
A
n
s
k
=
∑
i
=
k
n
A
[
i
]
B
[
i
−
k
]
k
!
Ans_k =\frac{\sum_{i=k}^nA[i]B[i-k]}{k!}
Ansk=k!∑i=knA[i]B[i−k]
考虑将B翻转,使A,B的下标之和为
k
k
k。
故
A
n
s
k
=
∑
i
=
k
n
A
[
i
]
B
[
k
−
i
]
k
!
Ans_k =\frac{\sum_{i=k}^nA[i]B[k-i]}{k!}
Ansk=k!∑i=knA[i]B[k−i]
转化后得到:
A
n
s
n
−
1
+
k
=
∑
i
=
k
n
A
[
i
]
B
[
n
−
1
+
k
−
i
]
k
!
Ans_{n-1+k} = \frac{\sum_{i=k}^nA[i]B[n-1+k-i]}{k!}
Ansn−1+k=k!∑i=knA[i]B[n−1+k−i]
然后就可以使用NTT优化了~
代码:
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int P = 998244353;
const int N = 1<<18;
const int G = 3;
int fac[N],inv[N],f[N],Ans[N],fac_sum[N],X[N],Y[N];
int n,m,sum;
int Pow(int n,int m){
int res = 1;
while(m){
if(m&1) res = 1LL*res*n%P;
n = 1LL*n*n%P;
m >>= 1;
}
return res;
}
void init(int N){
fac[0] = 1;
for(int i=1 ;i<=N ;i++) fac[i] = fac[i-1]*1LL*i%P;
inv[N] = Pow(fac[N],P-2);
for(int i=N-1 ;i>=0 ;i--) inv[i] = inv[i+1]*1LL*(i+1)%P;
}
int rev[N],w[2][N];
void init_NTT(int n){
for(int i=0 ;i<n;i++){
int x=i;int y=0;
for(int k=1;k<n;k<<=1,x>>=1)(y<<=1)|=(x&1);
rev[i]=y;
}
int v = Pow(G,(P-1)/n);
int dv = Pow(v,P-2);
w[0][0]=w[1][0]=1;
for(int i=1 ;i<n ;i++){
w[0][i]=w[0][i-1]*1ll*v%P;
w[1][i]=w[1][i-1]*1ll*dv%P;
}
}
void NTT(int *A,int n,int ff){
for(int i=0 ;i<n ;i++) if(i<rev[i])swap(A[i],A[rev[i]]);
for(int i=1;i<n;i<<=1)
for(int j=0,t=n/(i<<1);j<n;j+=(i<<1))
for(int k=0,l=0;k<i;k++,l+=t){
int x=A[i+j+k]*1ll*w[ff][l]%P;
int y=A[j+k];
A[j+k]=(x+y)%P;
A[i+j+k]=(y+P-x)%P;
}
if(ff){
int v=Pow(n,P-2);
for(int i=0 ;i<n ;i++) A[i]=A[i]*1ll*v%P;
}
}
void cal(){
if(sum == 0){
for(int i=0 ;i<=n ;i++) Ans[i] = f[i];
return;
}
sum = (P-sum)%P;
fac_sum[0] = 1;
for(int i=1 ;i<=n ;i++) fac_sum[i] = fac_sum[i-1]*1LL*sum%P;
int m = 1;
while(m <= 2*n+2) m<<=1;
for(int i=0 ;i<m ;i++) X[i] = Y[i] = 0;
init_NTT(m);
for(int i=0 ;i<=n ;i++){
X[i] = f[i]*1LL*fac[i]%P;
Y[n-i] = fac_sum[i]*1LL*inv[i]%P;
}
NTT(X,m,0);
NTT(Y,m,0);
for(int i=0 ;i<m ;i++) X[i] = (X[i]*1LL*Y[i])%P;
NTT(X,m,1);
for(int i=0 ;i<=n ;i++) Ans[i] = X[i+n]*1LL*inv[i]%P;
}
void solve(){
for(int i=0 ;i<=n ;i++) scanf("%d",&f[i]);
scanf("%d",&m);
sum = 0;
for(int i=1 ;i<=m ;i++){int x;scanf("%d",&x);sum = (sum+x)%P;}
cal();
for(int i=0 ;i<=n ;i++) printf("%d ",Ans[i]);puts("");
}
int main(){
init(N-1);
while(~scanf("%d",&n)) solve();
return 0;
}