题意
求\(\sum\limits_{k=0}^nS_k(x)\)这个多项式的每一项。
思路
直接代入伯努利数推柿子:
\(\sum\limits_{k=0}^n(S_k(x)+x^k)\)
\(=\sum\limits_{k=0}^na_kx^k+\sum\limits_{k=0}^na_kS_k(x)\)
\(=\sum\limits_{k=0}^na_kx^k+\frac{1}{k+1}\sum\limits_{j=0}^k\binom{k+1}{j}B_jx^{k+1-j}a_k\)
\(=\sum\limits_{k=0}^na_kx^k+\sum\limits_{k=0}^nk!a_k \sum\limits_{j=0}^k\frac{B_j}{j!}(k+1-j)!x^{k+1-j}\)
不妨令\(F(x)=x!a_x\),\(G(x)=\frac{B_x}{x!}\)
答案\(x^n\)的系数为:
\(=a_n+\sum\limits_{k=0}^n \sum\limits_{j=0}^k F(k)G(j)[k+1-j=n]\)
当然实际推的时候我还是先把\(x\)次项提到前面来的,这是差卷积的形式,翻转F/G即可。
code
点击查看代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e6+5;
const int mod=998244353;
ll ksm(ll a,ll b) {ll mul=1;for(;b;b>>=1,a=a*a%mod)if(b&1)mul=mul*a%mod;return mul;}
const int inv3=ksm(3,mod-2);
ll jc[N],ijc[N],inv[N];
ll binom(int n,int m) {return (n<m)?0:jc[n]*ijc[m]%mod*ijc[n-m]%mod;}
int up,L,rev[N];
ll gen[2][N];
void gt_up(int n) {
up=1;L=0;
while(up<=n) {up<<=1,L++;}
for(int i=1;i<up;i++) {rev[i]=(rev[i>>1]>>1)|((i&1)<<(L-1));}
}
void _clr(int n,ll *f) {for(int i=n;i<up;i++)f[i]=0;}
void _clr2(int n,ll *f,ll *g) {for(int i=n;i<up;i++)f[i]=g[i]=0;}
void gt_gen(int n) {
gt_up(n);
gen[0][up]=ksm(3,(mod-1)/up);gen[1][up]=ksm(inv3,(mod-1)/up);
for(int i=up;i;i>>=1) {
gen[0][i>>1]=gen[0][i]*gen[0][i]%mod;
gen[1][i>>1]=gen[1][i]*gen[1][i]%mod;
}
}
void init(int n) {
jc[0]=1;for(int i=1;i<=n;i++)jc[i]=jc[i-1]*i%mod;
ijc[n]=ksm(jc[n],mod-2);for(int i=n;i;i--)ijc[i-1]=ijc[i]*i%mod;
}
void NTT(ll *a,int op) {
for(int i=0;i<up;i++)if(rev[i]>i)swap(a[i],a[rev[i]]);
for(int mid=1;mid<up;mid<<=1) {
int len=mid<<1;ll w1=gen[op][len];
for(int i=0;i<up;i+=len) {
ll w=1;
for(int j=0;j<mid;j++,w=w*w1%mod) {
int p=i+j,q=p+mid;
ll x=a[p],y=a[q]*w;
a[p]=(x+y)%mod,a[q]=(x-y)%mod;
}
}
}
}
ll t[N];
void poly_inv(int n,ll *f,ll *b) {
// printf("*%d\n",n);
if(n==1) {b[0]=ksm(f[0],mod-2);return;}
poly_inv((n+1)>>1,f,b);
gt_up(n<<1);
for(int i=0;i<n;i++)t[i]=f[i];_clr(n,t);
NTT(t,0),NTT(b,0);
for(int i=0;i<up;i++)b[i]=(2-t[i]*b[i])%mod*b[i]%mod;
NTT(b,1);
for(int i=0,j=ksm(up,mod-2);i<n;i++)b[i]=b[i]*j%mod;_clr(n,b);
}
ll a[N],B[N],F[N],G[N];
int main() {
// freopen("data.in","r",stdin);
int n;scanf("%d",&n);n++;
gt_gen((n+1)<<1);init(n);
for(int i=0;i<n;i++) {scanf("%d",&a[i]);}
for(int i=0;i<n;i++) F[i]=ijc[i+1]; //左移一位
poly_inv(n,F,B);
gt_up((n+1)<<1);
for(int i=0;i<n;i++) F[i]=a[i]*jc[i]%mod,G[n-1-i]=B[i]%mod;
_clr(n+1,F);
NTT(F,0),NTT(G,0);
for(int i=0;i<up;i++)F[i]=F[i]*G[i]%mod;
NTT(F,1);
printf("%lld ",a[0]);
for(int i=1,j=ksm(up,mod-2);i<=n;i++) {
ll ans=F[n+i-2]*j%mod*ijc[i]%mod;
printf("%lld ",(ans+a[i]+mod)%mod);
}
return 0;
}