• BZOJ 4555: [Tjoi2016&Heoi2016]求和 第二类斯特林数+NTT


    (sum_{i=0}^{n}sum_{j=0}^{i}S(i,j) imes 2^j imes (j!))

    不妨将式子化为 (sum_{i=0}^{n}sum_{j=0}^{n}S(i,j) imes 2^j imes (j!)) (反正如果 (j>i) 的话 (S(i,j)=0))

    其中 (S(i,j)) 为第二类斯特林数.

    一般做这种推式子题时如果题面给的式子本身很简洁,那么八成是要把里面的东西暴力展开了.

    展开斯特林数:(S(n,m)=frac{1}{m!}sum_{i=0}^{m}(-1)^iinom{m}{i}(m-i)^n)

    原式可化为 (sum_{i=0}^{n}sum_{j=0}^{n}2^j(j!)sum_{k=0}^{j}frac{(-1)^k}{k!}frac{(j-k)^i}{(j-k)!})

    考虑将 (j) 移到前面,得 (sum_{j=0}^{n}2^j(j!)sum_{k=0}^{j}frac{(-1)^k}{k!}frac{sum_{i=0}^{n}(j-k)^i}{(j-k)!})

    然后上面那个用等比数列求和公式处理,为 (sum_{j=0}^{n}2^j(j!)sum_{k=0}^{j}frac{(-1)^k}{k!}frac{(j-k)^{n+1}-1}{(j-k-1)(j-k)!})

    后面那个是一个卷积的形式,用 NTT 加速即可(等比数列要特判一下公比为 1 的情况)

    #include <bits/stdc++.h>   
    #define G 3  
    #define N 200001     
    #define ll long long   
    #define mod 998244353       
    #define setIO(s) freopen(s".in","r",stdin)   
    using namespace std;          
    ll qpow(ll x,ll y) 
    {
        ll tmp=1ll; 
        while(y)  
        { 
            if(y&1)  tmp=tmp*x%mod; 
            x=x*x%mod, y>>=1;  
        }  
        return tmp;   
    }   
    ll Inv(ll x)  { return qpow(x,mod-2);  }   
    void NTT(ll *a,int len,int op) 
    {
        int i,j,mid,k;   
        for(i=k=0;i<len;++i) 
        {
            if(i>k)   swap(a[i],a[k]);   
            for(j=len>>1;(k^=j)<j;j>>=1);   
        }    
        for(mid=1;mid<len;mid<<=1) 
        {
            ll wn=qpow(G,(mod-1)/(mid<<1)); 
            if(op==-1)   wn=Inv(wn);  
            for(i=0;i<len;i+=mid<<1) 
            { 
                ll w=1ll;    
                for(j=0;j<mid;++j) 
                {
                    ll x=a[i+j],y=w*a[i+j+mid]%mod;     
                    a[i+j]=(x+y)%mod, a[i+j+mid]=(x-y+mod)%mod;     
                    w=w*wn%mod;     
                }
            }
        } 
        if(op==-1) 
        {
            ll rev=Inv(len); 
            for(i=0;i<len;++i)   a[i]=a[i]*rev%mod;         
        }
    }       
    ll fac[N],inv[N],f[N<<1],g[N<<1];        
    int main() 
    { 
        // setIO("input");  
        int i,j,n,limit;   
        scanf("%d",&n);        
        fac[0]=inv[0]=1ll; 
        for(i=1;i<N;++i)    fac[i]=fac[i-1]*1ll*i%mod,   inv[i]=Inv(fac[i]);   
        f[0]=1ll, g[0]=1ll, g[1]=n+1;    
        for(i=1;i<=n;++i)   f[i]=(qpow(-1,i)*inv[i]+mod)%mod;   
        for(i=2;i<=n;++i)   g[i]=(qpow(i,n+1)-1+mod)%mod*inv[i]%mod*Inv(i-1)%mod;       
        for(limit=1;limit<=2*n;limit<<=1);          
        NTT(f,limit,1),  NTT(g,limit,1);                   
        for(i=0;i<limit;++i)    f[i]=f[i]*g[i]%mod;   
        NTT(f,limit,-1);    
        ll ans=0ll;   
        for(i=0;i<=n;++i)    (ans+=qpow(2,i)*fac[i]%mod*f[i]%mod)%=mod;       
        printf("%lld
    ",ans);   
        return 0; 
    }   
    
  • 相关阅读:
    Intern Day7
    Intern Day7
    Intern Day7
    Intern Day6
    Intern Day6
    Intern Day6
    Intern Day6
    Intern Day6
    萧萧远树疏林外,一半秋山带夕阳
    飞线
  • 原文地址:https://www.cnblogs.com/guangheli/p/11886861.html
Copyright © 2020-2023  润新知