LGP3711题解
首先有伯努利数 \(B\),有一个结论是:
\[\sum_{i=0}^{n-1}i^k=\frac{1}{k+1}\sum_{i=0}^{k}\binom{k+1}{i}B_in^{k+1-i}
\]
世界用这个柿子,最后复合一个 \(x+1\) 就行了。
\[\sum_{i=0}^{x-1}i^k=k!\sum_{i=0}^{k}\frac{B_i}{i!}\frac{x^{k+1-i}}{(k+1-i)!}
\]
那么要求的答案就是:
\[\sum_{i=0}^{n}a_ii!\sum_{k=0}^{i}\frac{B_k}{k!}\frac{x^{i+1-k}}{(i+1-k)!}
\]
\[\sum_{i=0}^{n}a_ii!\sum_{k=1}^{i+1}\frac{x^k}{k!}\frac{B_{i+1-k}}{(i+1-k)!}
\]
设伯努利数的 EGF 为 \(B(x)\),我们知道 \(B(x)=\frac{x}{e^x-1}\):
\[\sum_{i=1}^{n+1}\frac{x^i}{i!}\sum_{j=i-1}^{n}j!a_j\frac{B_{j-i+1}}{(j-i+1)!}
\]
右边是一个差卷积。复杂度 \(O(n\log n)\)。
#include<algorithm>
#include<cstdio>
#include<cctype>
#include<vector>
#define IMP(lim,act) for(ui qwq=(lim),i=0;i^qwq;++i)act
typedef unsigned ui;
const ui M=1<<19|5,mod=998244353;
ui Inv[M],buf[M<<2];ui*now=buf,*w[23];
inline void swap(ui&a,ui&b){
ui c=a;a=b;b=c;
}
inline ui Add(const ui&a,const ui&b){
return a+b>=mod?a+b-mod:a+b;
}
inline ui Del(const ui&a,const ui&b){
return b>a?a-b+mod:a-b;
}
inline ui max(const ui&a,const ui&b){
return a>b?a:b;
}
inline void write(ui n){
static char s[10];ui top(0);while(s[++top]=n%10^48,n/=10);while(putchar(s[top--]),top);
}
inline ui read(){
ui n(0);char s;while(!isdigit(s=getchar()));while(n=n*10+(s&15),isdigit(s=getchar()));return n;
}
inline ui pow(ui a,ui b=mod-2){
ui ans(1);for(;b;b>>=1,a=1ull*a*a%mod)if(b&1)ans=1ull*ans*a%mod;return ans;
}
inline ui Getlen(const ui&n){
ui len(0);while((1<<len)<n)++len;return len;
}
inline void init(const ui&n){
const ui&m=Getlen(n);w[m]=now;now+=1<<m;Inv[1]=1;
for(ui i=2;i<n;++i)Inv[i]=1ull*(mod-mod/i)*Inv[mod%i]%mod;
w[m][0]=1;w[m][1]=pow(3,mod-1>>m+1);for(ui i=2;i<(1<<m);++i)w[m][i]=1ull*w[m][i-1]*w[m][1]%mod;
for(int k=m-1;k>=0&&(w[k]=now,now+=1<<k);--k)IMP(1<<k,w[k][i]=w[k+1][i<<1]);
}
struct Poly{
std::vector<ui>F;
Poly(const Poly&G){F=G.F;}
Poly(const std::vector<ui>G){F=G;}
Poly(const ui&x=0){if(x)F=std::vector<ui>(x);}
inline Poly&resize(const ui&len){
F.resize(len);return*this;
}
inline ui size()const{
return F.size();
}
inline ui&operator[](const ui&id){
return F[id];
}
inline void push_back(const ui&x){
F.push_back(x);
}
inline Poly&reverse(){
std::reverse(F.begin(),F.end());return*this;
}
inline Poly operator>>(const ui&x){
ui i;Poly G;IMP(F.size()-x,G.push_back(F[i+x]));return G;
}
inline Poly operator<<(const ui&x){
ui i;Poly G;G.resize(x);IMP(F.size(),G.push_back(F[i]));return G;
}
inline ui operator()(const ui&x){
ui i,y(1),ans(0);IMP(F.size(),ans=(ans+1ull*F[i]*y)%mod),y=1ull*y*x%mod;return ans;
}
inline void px(Poly G){
F.resize(max(F.size(),G.size()));G.resize(F.size());
for(ui i(0);i^F.size();++i)F[i]=1ull*F[i]*G[i]%mod;
}
inline Poly&Der(){
for(ui i(1);i^F.size();++i)F[i-1]=1ull*F[i]*i%mod;F.pop_back();return*this;
}
inline Poly&Int(){
F.push_back(0);
for(ui i(F.size()-1);i;--i)F[i]=1ull*F[i-1]*::Inv[i]%mod;F[0]=0;return*this;
}
inline void DFT(const ui&M){
ui i,k,d,x,y,len,*W,*L,*R;F.resize(1<<M);
for(len=F.size()>>1,d=M-1;len;--d,len>>=1)for(k=0;k^F.size();k+=len<<1){
W=w[d];L=&F[k];R=&F[k|len];IMP(len,(x=*L,y=*R)),*L++=Add(x,y),*R++=1ull**W++*Del(x,y)%mod;
}
}
inline void IDFT(const ui&M){
ui i,k,d,x,y,len,*W,*L,*R;F.resize(1<<M);
for(len=1,d=0;len^F.size();len<<=1,++d)for(k=0;k^F.size();k+=len<<1){
W=w[d];L=&F[k];R=&F[k|len];IMP(len,(x=*L,y=1ull**W++**R%mod)),*L++=Add(x,y),*R++=Del(x,y);
}
k=::pow(F.size());IMP(F.size(),F[i]=1ull*F[i]*k%mod);for(i=1;(i<<1)<F.size();++i)swap(F[i],F[F.size()-i]);
}
inline Poly operator+(Poly G)const{
Poly F=this->F;ui i;F.resize(max(F.size(),G.size()));G.resize(F.size());
IMP(F.size(),F[i]=Add(F[i],G[i]));return F;
}
inline Poly operator-(Poly G)const{
Poly F=this->F;ui i;F.resize(max(F.size(),G.size()));G.resize(F.size());
IMP(F.size(),F[i]=Del(F[i],G[i]));return F;
}
inline Poly operator*(const ui&x)const{
Poly F=this->F;ui i;
IMP(F.size(),F[i]=1ull*F[i]*x%mod);return F;
}
inline Poly operator*(Poly G)const{
Poly F=*this;const ui&m=F.size()+G.size()-1,&len=Getlen(m);
F.DFT(len);G.DFT(len);F.px(G);F.IDFT(len);return F.resize(m);
}
inline Poly operator/(Poly G){
Poly F=*this,sav;const ui&m=F.size()-G.size()+1;
sav.resize(m);IMP(m,sav[i]=G.size()+i<m?0:G[G.size()-m+i]);
sav.reverse().inv();sav*=F.reverse();
return sav.resize(m).reverse();
}
inline Poly operator%(Poly G){
return(*this-*this/G*G).resize(G.size()-1);
}
inline Poly&inv(){
Poly b1,b2,b3;const ui&m=Getlen(F.size());if(!F.empty())b1.push_back(::pow(F[0]));
for(ui len=1;len<=m;++len){
b3=b1*2;(b2=F).resize(1<<len);
b1.DFT(len+1);b1.px(b1);b2.DFT(len+1);b1.px(b2);b1.IDFT(len+1);
b1=b3-b1.resize(1<<len);
}
return*this=b1.resize(F.size());
}
inline Poly&ln(){
const ui&m=F.size()-1;Poly G=*this;return(this->Der()*=G.inv()).resize(m).Int();
}
inline Poly&exp(){
Poly b1,b2,b3;const ui&m=Getlen(F.size());b1.push_back(1);
for(ui len=1;len<=m;++len){
b3=b2=b1;b2.resize(1<<len).ln();b2=(*this-b2).resize(1<<len);++b2[0];
b2.DFT(len);b3.DFT(len);b2.px(b3);b2.IDFT(len);b1.resize(1<<len);
IMP(1<<len-1,b1[1<<len-1|i]=b2[1<<len-1|i]);
}
return*this=b1.resize(F.size());
}
inline Poly&sqrt(){
Poly b1,b2;const ui&m=Getlen(F.size());b1.push_back(1);
for(ui len=1;len<=m;++len){
b2=(b1*2).resize(1<<len).inv();
b1.DFT(len);b1.px(b1);b1.IDFT(len);
b1=((*this+b1).resize(1<<len)*b2).resize(1<<len);
}
return*this=b1.resize(F.size());
}
inline Poly&pow(const ui&k){
ui i;ln();IMP(F.size(),F[i]=1ull*F[i]*k%mod);return exp();
}
inline Poly&operator>>=(const ui&x){
return*this=operator>>(x);
}
inline Poly&operator<<=(const ui&x){
return*this=operator<<(x);
}
inline Poly&operator+=(const Poly&G){
return*this=*this+G;
}
inline Poly&operator-=(const Poly&G){
return*this=*this-G;
}
inline Poly&operator*=(const Poly&G){
return*this=*this*G;
}
inline Poly&operator/=(const Poly&G){
return*this=*this/G;
}
inline Poly&operator%=(const Poly&G){
return*this=*this%G;
}
};
inline Poly resize(Poly F,const ui&n){
return F.resize(n);
}
inline Poly reverse(Poly F){
return F.reverse();
}
inline Poly Int(Poly F){
return F.Int();
}
inline Poly Der(Poly F){
return F.Der();
}
inline Poly px(Poly F,Poly G){
return F.px(G),F;
}
inline Poly inv(Poly F){
return F.inv();
}
inline Poly ln(Poly F){
return F.ln();
}
inline Poly exp(Poly F){
return F.exp();
}
inline Poly sqrt(Poly F){
return F.sqrt();
}
inline Poly pow(Poly F,const ui&k){
return F.pow(k);
}
int n,a[M],fac[M],ifac[M];Poly F,G;
signed main(){
n=read();init(n+1<<1);for(int i=0;i<=n;++i)a[i]=read();F.resize(n+1);G.resize(n+1);
fac[0]=ifac[0]=1;for(int i=1;i<=n+1;++i)fac[i]=1ll*fac[i-1]*i%mod,ifac[i]=1ll*ifac[i-1]*Inv[i]%mod;
for(int i=0;i<=n;++i)F[i]=1ll*a[i]*fac[i]%mod,G[i]=ifac[i+1];F=F*G.inv().reverse()>>n;F<<=1;
G.resize(n+2);for(int i=0;i<=n+1;++i)G[i]=ifac[i];F=F*G.reverse()>>n+1;
for(int i=0;i<=n+1;++i)write(1ll*F[i]*ifac[i]%mod),putchar(32);
}