Luogu P4091 [HEOI2016/TJOI2016]求和

Link

\[\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);
}
posted @ 2020-04-21 16:19  Shiina_Mashiro  阅读(386)  评论(0编辑  收藏  举报