令 $f(i,j)$ 表示 $j$ 的 $i$ 阶前缀和.
那么有 $f(i,j)=sum_{j=1}^{i} f(i-1,j)$,这个可以直接多项式快速幂.
时间复杂度是 $O(n log^2 n)$ 或 $O(n log n)$ ,但是常数大而且第二种不好写.
考虑计算每一个位置 $j leqslant i$ 对 $i$ 位置的贡献.
令 $p(i,j,k)$ 表示 $j$ 对 $i$ 的 $k$ 阶前缀和的贡献系数,那么有:
$p(i,j,k)=sum_{t=1}^{i} p(t,j,k-1)$.
组合意义上可以看作将 $j-i$ 分成 $k$ 份的方案数,即 $inom{j-i+k-1}{k-1}$.
构建生成函数 $B(x)=sum_{i=0}^{infty} inom{i+k-1}{i} x^i$ 然后和 $A(x)=sum_{i=0}^{n} a_{i} x^i$ 卷一下即可.
code:
#include <cstdio> #include <cstring> #include <algorithm> #define N 400009 #define ll long long #define mod 998244353 #define setIO(s) freopen(s".in","r",stdin) using namespace std; ll kth; int A[N],B[N],inv[N],n; int qpow(int x,int y) { int tmp=1; for(;y;y>>=1,x=(ll)x*x%mod) if(y&1) tmp=(ll)tmp*x%mod; return tmp; } int get_inv(int x) { return qpow(x,mod-2); } void NTT(int *a,int len,int op) { for(int i=0,k=0;i<len;++i) { if(i>k) swap(a[i],a[k]); for(int j=len>>1;(k^=j)<j;j>>=1); } for(int l=1;l<len;l<<=1) { int w=qpow(3,(mod-1)/(l<<1)),wn,x,y; if(op==-1) w=get_inv(w); for(int i=0;i<len;i+=l<<1) { wn=1; for(int j=0;j<l;++j) { x=a[i+j],y=(ll)a[i+j+l]*wn%mod; a[i+j]=(ll)(x+y)%mod; a[i+j+l]=(ll)(x-y+mod)%mod; wn=(ll)wn*w%mod; } } } if(op==-1) { int p=get_inv(len); for(int i=0;i<len;++i) { a[i]=(ll)a[i]*p%mod; } } } void init() { inv[1]=1; for(int i=2;i<N;++i) { inv[i]=(ll)(mod-mod/i)*inv[mod%i]%mod; } inv[0]=1; for(int i=1;i<N;++i) { inv[i]=(ll)inv[i-1]*inv[i]%mod; } ll mul=1; for(int i=0;i<=n;++i) { B[i]=(ll)mul%mod*inv[i]%mod; mul=mul*1ll*((kth+i)%mod)%mod; } } int main() { // setIO("input"); scanf("%d%lld",&n,&kth); init(); for(int i=1;i<=n;++i) scanf("%d",&A[i]); int l=1; for(;l<(2*n+1);l<<=1); NTT(A,l,1),NTT(B,l,1); for(int i=0;i<l;++i) { A[i]=(ll)A[i]*B[i]%mod; } NTT(A,l,-1); for(int i=1;i<=n;++i) { printf("%d ",A[i]); } return 0; }