Luogu P4091 [HEOI2016/TJOI2016]求和
\[\begin{aligned}
ans&=\sum\limits_{i=0}^n\sum\limits_{j=0}^i\left\{i\atop j\right\}2^jj!\\
&=\sum\limits_{i=0}^n\sum\limits_{j=0}^n\left\{i\atop j\right\}2^jj!\\
&=\sum\limits_{i=0}^n\sum\limits_{j=0}^n2^j\sum\limits_{k=0}^j(-1)^{j-k}{j\choose k}k^i\\
&=\sum\limits_{i=0}^n\sum\limits_{j=0}^n2^j\sum\limits_{k=0}^j(-1)^{j-k}{j\choose k}k^i\\
&=\sum\limits_{j=0}^n\sum\limits_{k=0}^j(-1)^{j-k}{j\choose k}2^j[n+1]_k\\
&=\sum\limits_{k=0}^n[n+1]_k\sum\limits_{i=k}^n(-1)^{i-k}{i\choose k}2^i\\
&=\sum\limits_{k=0}^n(-1)^k[n+1]_k\sum\limits_{i=k}^n(-2)^i{i\choose k}\end{aligned}
\]
设\(a_i=\sum\limits_{j=i}^n(-2)^j{j\choose i}\),那么\(ans=\sum\limits_{k=0}^n(-1)^k[n+1]_ka_k\)。
\([n+1]_k\)是可以利用线性筛求出来的,那么我们现在考虑如何线性求出\(a\)。
\(a_0\)是可以轻松线性计算的,那么我们考虑递推。
\[\begin{aligned}
a_i&=\sum\limits_{j=i}^n(-2)^j{j\choose i}\\
&=\sum\limits_{j=i}^n(-2)^j({j-1\choose i}+{j-1\choose i-1})\\
&=(-2)(\sum\limits_{j=i}^{n-1}(-2)^j{j\choose i}+\sum\limits_{j=i-1}^{n-1}(-2)^j{j\choose i-1})\\
&=-2(a_i+a_{i-1})+2(-2)^n{n+1\choose i}\\
&=\frac23((-2)^n{n+1\choose i}-a_{i-1})
\end{aligned}
\]
很显然预处理阶乘就可以线性计算了。
#include<cstdio>
const int N=100007,P=998244353;
int fac[N],ifac[N],inv[N],pw[N],is[N],pr[N],pw2[N],a[N];
void inc(int&a,int b){a+=b-P,a+=a>>31&P;}
void dec(int&a,int b){a-=b,a+=a>>31&P;}
int mul(int a,int b){return 1ll*a*b%P;}
int pow(int a,int b){int r=1;for(;b;b>>=1,a=mul(a,a))if(b&1)r=mul(a,r);return r;}
int C(int n,int m){return 1ll*fac[n]*ifac[n-m]%P*ifac[m]%P;}
int main()
{
int n,m=0,ans=0;scanf("%d",&n),fac[0]=fac[1]=ifac[0]=ifac[1]=inv[0]=inv[1]=pw2[0]=1,pw2[1]=P-2;
for(int i=2;i<=n;++i)
{
if(!is[i]) pr[++m]=i,pw[i]=pow(i,n+1);
for(int j=1;pr[j]*i<=n;++j){is[i*pr[j]]=1,pw[i*pr[j]]=mul(pw[i],pw[pr[j]]);if(!(i%pr[j]))break;}
}
for(int i=2;i<=n+3;++i) fac[i]=mul(fac[i-1],i),ifac[i]=mul(ifac[i-1],inv[i]=mul(P-P/i,inv[P%i])),pw2[i]=mul(pw2[i-1],P-2);
for(int i=0;i<=n;++i) inc(a[0],pw2[i]);
for(int i=1;i<=n;++i) a[i]=2ll*inv[3]*(1ll*pw2[n]*C(n+1,i)%P-a[i-1]+P)%P;
for(int i=2;i<=n;++i) (i&1? dec:inc)(ans,(pw[i]-1ll)*a[i]%P*inv[i-1]%P);
inc(ans,a[0]),dec(ans,mul(a[1],n+1)),printf("%d",ans);
}