BZOJ 5093: [Lydsy1711月赛]图的价值 第二类斯特林数+NTT

code:

#include <bits/stdc++.h>   
#define LL long long 
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;   
const int G=3,mod=998244353,N=400005,phi=998244352;              
inline int qpow(int x,int y) 
{
    int tmp=1;   
    for(;y;y>>=1,x=1ll*x*x%mod)    if(y&1)    tmp=1ll*tmp*x%mod;  
    return tmp;    
}
inline int INV(int x) { return qpow(x,mod-2); }         
inline void NTT(int *a,int len,int flag) 
{
    int i,j,k,mid;  
    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) 
    {   
        int wn=qpow(G,(mod-1)/(mid<<1));   
        if(flag==-1)    wn=INV(wn);   
        for(i=0;i<len;i+=mid<<1) 
        {
            int w=1;   
            for(j=0;j<mid;++j) 
            {
                int x=a[i+j],y=1ll*w*a[i+j+mid]%mod;   
                a[i+j]=1ll*(x+y)%mod,  a[i+j+mid]=1ll*(x-y+mod)%mod;    
                w=1ll*w*wn%mod;   
            }
        }
    }   
    if(flag==-1) 
    {     
        int rev=INV(len);   
        for(i=0;i<len;++i)    a[i]=1ll*a[i]*rev%mod;   
    }
}     
int f[N<<2],g[N<<2],fac[N],inv[N];   
void Initialize(int Lim) 
{   
    int i,j,limit;                   
    inv[0]=fac[0]=1;     
    for(i=1;i<=Lim;++i)    fac[i]=1ll*fac[i-1]*i%mod,inv[i]=INV(fac[i]);   
    for(i=0;i<=Lim;++i) 
    {
        f[i]=inv[i];       
        if(i&1)    f[i]=mod-f[i];    
        g[i]=1ll*inv[i]*qpow(i,Lim)%mod;                
    }   
    for(limit=1;limit<=2*(Lim+1);limit<<=1);   
    NTT(f,limit,1),NTT(g,limit,1);  
    for(i=0;i<limit;++i)    f[i]=1ll*f[i]*g[i]%mod;   
    NTT(f,limit,-1);                   
}
int main() 
{ 
    // setIO("input");    
    int i,j,n,k,ans=0,Lim; 
    scanf("%d%d",&n,&k),Lim=min(n-1,k);  
    Initialize(k);           
    int now=1,tot=n-1;         
    for(i=0;i<=Lim;++i) 
    {         
        int delta=1ll*f[i]*now%mod*qpow(2,n-1-i)%mod;                     
        ans=(ans+delta)%mod;     
        now=1ll*now*tot%mod;   
        --tot;   
    }                 
    ans=1ll*ans*n%mod;  
    ans=1ll*ans*qpow(2,1ll*(n-1)*(n-2)/2%phi)%mod;   
    printf("%d\n",ans);     
    return 0; 
}

猜你喜欢

转载自www.cnblogs.com/guangheli/p/11890324.html