[HEOI2016/TJOI2016]求和

题意

i=0nj=0iSji2jj!mod998244353 ∑ i = 0 n ∑ j = 0 i S i j 2 j j ! mod 998244353

Smn S n m 表示第二类斯特林数


题解

考虑到当 i<j i < j Sji=0 S i j = 0

i=0nj=0nSji2jj! ⇒ ∑ i = 0 n ∑ j = 0 n S i j 2 j j !

j=0n2jj!i=0nSji ⇒ ∑ j = 0 n 2 j j ! ∑ i = 0 n S i j

考虑到

Smn=1m!i=0m(1)i(mi)(mi)n=i=0m(1)ii!(mi)n(mi)! S n m = 1 m ! ∑ i = 0 m ( − 1 ) i ( m i ) ( m − i ) n = ∑ i = 0 m ( − 1 ) i i ! ( m − i ) n ( m − i ) !

那么

j=0n2jj!i=0nk=0j(1)kk!(jk)i(ik)! ⇒ ∑ j = 0 n 2 j j ! ∑ i = 0 n ∑ k = 0 j ( − 1 ) k k ! ( j − k ) i ( i − k ) !

j=0n2jj!k=0j(1)kk!ni=0(jk)i(jk)! ⇒ ∑ j = 0 n 2 j j ! ∑ k = 0 j ( − 1 ) k k ! ∑ i = 0 n ( j − k ) i ( j − k ) !

f(i)=(1)ii!,g(i)=nj=0iji!=in+11(i1)i!, f ( i ) = ( − 1 ) i i ! , g ( i ) = ∑ j = 0 n i j i ! = i n + 1 − 1 ( i − 1 ) i ! , 特别的 g(0)=n+1 g ( 0 ) = n + 1

j=0n2jj!(f×g)(j) ⇒ ∑ j = 0 n 2 j j ! ( f × g ) ( j )

这样求一遍 NTT N T T 即可

#include<bits/stdc++.h>
#define fp(i,a,b) for(register int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(register int i=a,I=b-1;i>I;--i)
#define go(u) for(register int i=fi[u],v=e[i].to;i;v=e[i=e[i].nx].to)
#define file(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=3e5+5,P=998244353,G=3;
typedef int arr[N];
typedef long long ll;
int n,ans,K;arr a,b,R,wn,Mi,fac,inv,ifac;
inline int pls(int a,int b){return a+=b,a<P?a:a-P;}
inline int sub(int a,int b){return a-=b,a<0?a+P:a;}
inline int fpm(int a,int b){int x=1;for(;b;b>>=1,a=(ll)a*a%P)if(b&1)x=(ll)x*a%P;return x;}
inline void init(){for(int i=0,j=0;i<K;++i){R[i]=j;for(int l=K>>1;(j^=l)<l;l>>=1);}}
inline void dft(int*a,int ty=1){
    fp(i,0,K-1)if(i>R[i])swap(a[i],a[R[i]]);
    for(int i=2;i<=K;i<<=1){
        const int d=i>>1,e=ty==1?fpm(G,(P-1)/i):fpm(G,P-1-(P-1)/i);int o;
        fp(i,1,d-1)wn[i]=(ll)wn[i-1]*e%P;
        for(int*x=a;x!=a+K;x+=i)fp(k,0,d-1)
            o=(ll)x[k+d]*wn[k]%P,x[k+d]=sub(x[k],o),x[k]=pls(x[k],o);
    }if(ty^1){
        const int inv=fpm(K,P-2);
        fp(i,0,K-1)a[i]=(ll)a[i]*inv%P;
    }
}
int main(){
    #ifndef ONLINE_JUDGE
        file("s");
    #endif
    scanf("%d",&n);
    inv[1]=a[0]=b[0]=wn[0]=Mi[0]=1;a[1]=P-1;b[1]=n+1;
    fac[0]=1;fp(i,1,n)fac[i]=(ll)fac[i-1]*i%P,Mi[i]=pls(Mi[i-1],Mi[i-1]);
    ifac[n]=fpm(fac[n],P-2);fd(i,n,1)ifac[i-1]=(ll)ifac[i]*i%P;
    fp(i,2,n)inv[i]=(ll)(P-P/i)*inv[P%i]%P;
    fp(i,2,n)a[i]=i&1?P-ifac[i]:ifac[i],
             b[i]=(ll)(fpm(i,n+1)-1)*inv[i-1]%P*ifac[i]%P;
    K=1;while(K<=n)K<<=1;K<<=1;init();
    dft(a),dft(b);fp(i,0,K-1)a[i]=(ll)a[i]*b[i]%P;dft(a,-1);
    fp(i,0,n)ans=pls(ans,(ll)Mi[i]*fac[i]%P*a[i]%P);
    printf("%d\n",ans);
return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值