bzoj4555:[Tjoi2016&Heoi2016]求和

传送门

首先我们需要知道第二类斯特林数的通项公式
\[ S(n,m)=\frac{1}{m!}\sum_{k=0}^{m}(-1)^k\binom{m}{k}(m-k)^n \]
然后我们就可以将题目给的式子里的第二类斯特林数拆开
\[ f(n)=\sum_{i=0}^{n}\sum_{j=0}^{i}\frac{1}{j!}\sum_{k=0}^{j}(-1)^k\binom{j}{k}(j-k)^i2^j(j!)\\ f(n)=\sum_{i=0}^{n}\sum_{j=0}^{i}2^j\sum_{k=0}^{j}(-1)^k\binom{j}{k}(j-k)^i\\ \]
然后发现这个式子貌似做不下去了,然后考虑对于\(j>i\)\(S(i,j)\)都是没有意义的
\[ f(n)=\sum_{i=0}^{n}\sum_{j=0}^{n}2^j\sum_{k=0}^{j}(-1)^k\binom{j}{k}(j-k)^i\\ \]
然后把组合数拆开
\[ f(n)=\sum_{i=0}^{n}\sum_{j=0}^{n}2^j\sum_{k=0}^{j}(-1)^k\frac{j!}{k!(j-k)!}(j-k)^i\\ \]
然后调换一下\(\sum\)
\[ f(n)=\sum_{j=0}^{n}2^jj!\sum_{k=0}^{j}\frac{(-1)^k}{k!}\frac{\sum_{i=0}^{n}(j-k)^i}{(j-k)!}\\ \]

\[ f(i)=\frac{(-1)^i}{i!}\\ g(i)=\frac{\sum_{j=0}^{n}i^j}{i!} \]
那么
\[ f(n)=\sum_{j=0}^{n}2^jj!\sum_{k=0}^{j}f(k)g(j-k) \]
可以发现后面是一个卷积的形式,可以用ntt快速计算,然后这个题就做完了

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#include<cmath>
using namespace std;
void read(int &x){
    char ch;bool ok;
    for(ok=0,ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')ok=1;
    for(x=0;isdigit(ch);x=x*10+ch-'0',ch=getchar());if(ok)x=-x;
}
#define rg register
const int maxn=4e5+10,mod=998244353,g=3,gi=332748118;
int n,a[maxn],b[maxn],m,fac[maxn],inv[maxn],len,ans,r[maxn];
int mul(int x,int y){return 1ll*x*y-1ll*x*y/mod*mod;}
int add(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int del(int x,int y){return x-y<0?x-y+mod:x-y;}
int mi(int a,int b){
    int ans=1;
    while(b){
        if(b&1)ans=mul(ans,a);
        b>>=1,a=mul(a,a);
    }
    return ans;
}
void ntt(int *a,int f){
    for(rg int i=0;i<n;i++)if(r[i]>i)swap(a[i],a[r[i]]);
    for(rg int i=1;i<n;i<<=1){
        int wn=mi(f?g:gi,(mod-1)/(i<<1));
        for(rg int j=0;j<n;j+=i<<1){
            int w=1;
            for(rg int k=0;k<i;k++){
                int x=a[j+k],y=mul(w,a[i+j+k]);
                a[j+k]=add(x,y),a[j+k+i]=del(x,y),w=mul(w,wn);
            }
        }
    }
    if(f)return ;int inv=mi(n,mod-2);
    for(rg int i=0;i<n;i++)a[i]=mul(a[i],inv);
}
int sum(int q){return q==1?n+1:mul(del(mi(q,n+1),1),mi(del(q,1),mod-2));}
int main(){
    read(n);fac[0]=1;
    for(rg int i=1;i<=n;i++)fac[i]=mul(fac[i-1],i);
    inv[n]=mi(fac[n],mod-2);
    for(rg int i=n-1;i>=0;i--)inv[i]=mul(inv[i+1],i+1);
    for(rg int i=0;i<=n;i++)a[i]=mul((i&1?mod-1:1),inv[i]);
    for(rg int i=0;i<=n;i++)b[i]=mul(sum(i),inv[i]);
    m=n+n;for(n=1;n<=m;n<<=1)len++;m=m/2;
    for(rg int i=0;i<=n;i++)r[i]=(r[i>>1]>>1)|((i&1)<<(len-1));
    ntt(a,1),ntt(b,1);
    for(rg int i=0;i<=n;i++)a[i]=mul(a[i],b[i]);
    ntt(a,0);
    for(rg int i=0;i<=m;i++)ans=add(ans,mul(mi(2,i),mul(fac[i],a[i])));
    printf("%d\n",ans);
}
posted @ 2019-04-24 12:05 蒟蒻--lichenxi 阅读(...) 评论(...) 编辑 收藏