zoukankan      html  css  js  c++  java
  • 【题解】有标号的DAG计数4

    [HZOI 2015] 有标号的DAG计数 IV

    我们已经知道了(f_i)表示不一定需要联通的(i)节点的dag方案,考虑合并

    参考【题解】P4841 城市规划(指数型母函数+多项式Ln),然后答案(h_i)母函数(H(x))就这样解

    由于

    [H(x)=sum_{i=0}^{inf} dfrac {(F(x))^i} {i!} ]

    [H(x)=e^{F(x)} ]

    (ln)就好了

    //@winlere
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
     
     
    using namespace std;  typedef long long ll;
    inline int qr(){
          register int ret=0,f=0;
          register char c=getchar();
          while(c<48||c>57)f|=c==45,c=getchar();
          while(c>=48&&c<=57) ret=ret*10+c-48,c=getchar();
          return f?-ret:ret;
    }
     
     
    namespace poly{
          const int maxn=1<<19|1;
          int a[maxn],b[maxn],A[maxn],B[maxn],r[maxn];
          int savlen;
          inline void getr(const int&len){
    	    if(len==savlen)return;
    	    int cnt=0;
    	    for(register int t=1;t<len;t<<=1)++cnt;
    	    for(register int t=1;t<len;++t)
    		  r[t]=r[t>>1]>>1|(t&1)<<cnt>>1;
          }
          const int mod=998244353;
          const int g=3;
          inline int ksm(ll base,ll p){
    	    register int ret=1;
    	    for(base%=mod;p;p>>=1,base=1ll*base*base%mod)
    		  if(p&1) ret=1ll*ret*base%mod;
    	    return ret;
          }
          const int gi=ksm(3,mod-2);
          
     
          inline void NTT(int*a,const int&len,const int&tag){
    	    getr(len);
    	    for(register int t=1;t<len;++t)
    		  if(r[t]>t) swap(a[t],a[r[t]]);
    	    int *a1,*a0,s=g;
    	    if(tag!=1) s=gi;
    	    for(register int t=1,wn;t<len;t<<=1){
    		  wn=ksm(s,(mod-1)/(t<<1));
    		  for(register int i=0;i<len;i+=t<<1){
    			a1=(a0=a+i)+t;
    			for(register int j=0,w=1,tm;j<t;++j,++a1,++a0,w=1ll*w*wn%mod){
    			      tm=1ll**a1*w%mod;
    			      *a1=(*a0-tm)%mod;
    			      *a0=(*a0+tm)%mod;
    			      if(*a1<0)*a1+=mod;
    			}
    		  }
    	    }
    	    if(tag!=1)
    		  for(register int t=0,in=ksm(len,mod-2);t<len;++t)
    			a[t]=1ll*a[t]*in%mod;
          }
          
          void INV(int*a,int*b,const int&len){
    	    if(len==1){b[0]=ksm(a[0],mod-2);return;}
    	    INV(a,b,len>>1);
    	    for(register int t=0;t<len;++t) A[t]=a[t],B[t]=b[t];
    	    NTT(A,len<<1,1);NTT(B,len<<1,1);
    	    for(register int t=0,w=len<<1;t<w;++t) A[t]=1ll*A[t]*B[t]%mod*B[t]%mod;
    	    NTT(A,len<<1,-1);
    	    for(register int t=0;t<len;++t) b[t]=((b[t]+b[t])%mod-A[t]+mod)%mod;
    	    memset(A,0,sizeof A);
    	    memset(B,0,sizeof B);
          }
          
          inline void inter(int*a,int*b,const int&len){
    	    for(register int t=len;t;--t)
    		  b[t]=1ll*a[t-1]*ksm(t,mod-2)%mod;
    	    b[0]=0;
          }
          
          inline void dev(int*a,int*b,const int&len){
    	    for(register int t=0;t<len-1;++t)
    		  b[t]=1ll*a[t+1]*(t+1)%mod;
    	    b[len-1]=0;
          }
     
          
          inline void LN(int*a,int*b,const int&len){
    	    static int C[maxn];
    	    memset(C,0,sizeof C);
    	    INV(a,b,len);
    	    dev(a,C,len);
    	    NTT(C,len<<1,1);
    	    NTT(b,len<<1,1);
    	    for(register int t=0;t<len<<1;++t) b[t]=1ll*b[t]*C[t]%mod;
    	    NTT(b,len<<1,-1);
    	    inter(b,C,len);
    	    for(register int t=0;t<len;++t) b[t]=C[t];
    	    
          }
          
    }
     
     
     
     
    int g[1<<19|1],f[1<<19|1];
    int jc[100005];
    int inv[100005];
    int n;
    const int mod=998244353;
    int main(){
          freopen("dagIV.in","r",stdin);
          freopen("dagIV.out","w",stdout);
          n=qr();
          jc[0]=1;
          inv[0]=1;
          for(register int t=1;t<=n;++t)
    	    jc[t]=1ll*jc[t-1]*t%mod;
          using poly::ksm;
          inv[n]=ksm(jc[n],mod-2);
          for(register int t=n-1;t;--t) inv[t]=1ll*(t+1)*inv[t+1]%mod;
          for(register int t=1;t<=n;++t){
    	    g[t]=1ll*ksm(ksm(2,1ll*t*(t-1)/2),mod-2)*inv[t]%mod;
    	    if(t&1) g[t]=mod-g[t];
          }       
          g[0]=1;
          int k=1;
          while(k<=n+2)k<<=1;
          poly::INV(g,f,k);
          memset(g,0,sizeof g);
          for(register int t=1;t<=n;++t)
    	    g[t]=1ll*ksm(2,1ll*t*(t-1)/2)%mod*f[t]%mod;
          g[0]=1;
          memset(f,0,sizeof f);
          //cout<<endl;
          poly::LN(g,f,k);
          //for(register int t=0;t<k;++t) cout<<f[t]<<' ';
          printf("%lld
    ",1ll*jc[n]*f[n]%mod);
          return 0;
    }
    
  • 相关阅读:
    oracle 查询 主机名和对应的IP地址
    mysql 常用命令
    linux 下 mysql-5.5.8 安装
    oracle批量插入数据(测试)
    Oracle数据库查询优化(上百万级记录如何提高查询速度)
    针对分区表一个月3个分区定期清理脚本
    C语言中%p,%u,%lu都有什么用处
    MAC下查看环境变量的值的方法
    Mac 终端 Linux 命令总结(简单命令)
    TypeScript学习-TypeScript环境配置
  • 原文地址:https://www.cnblogs.com/winlere/p/11258205.html
Copyright © 2011-2022 走看看