zoukankan      html  css  js  c++  java
  • Come OJ P3803 Farewell 容斥+快速子集变换

    题意:给定 $n$ 个点,$m$ 条边的图,求有多少子图满足子图 (即边可以任意定方向或消失)是一个 DAG ?

    $f(S)=sum_{T subseteq S} (-1)^{|T|-1} inom{|S|}{|T|} f(S-T) 2^{E(S)-E(T)-E(S-T)}$.  

    这里 $E(S)$ 表示点集 $S$ 包含的边的数量.    

    直接套用这个式子,然后用 FWT 的 or 运算做一下子集卷积即可.    

    #include <bits/stdc++.h> 
    #define N 23    
    #define ll long long 
    #define mod 998244353 
    #define setIO(s) freopen(s".in","r",stdin)
    using namespace std;    
    int inv2,n,m,mp[N][N],bin[N],size[1<<N];   
    int E[1<<N],dp[N][1<<N],g[N][1<<N];     
    inline int qpow(int x,int y) 
    {
        int tmp=1;   
        for(;y;y>>=1,x=(ll)x*x%mod)  
            if(y&1) 
                tmp=(ll)tmp*x%mod;  
        return tmp; 
    }
    inline int INV(int x) { return qpow(x,mod-2); }
    void FWT(int *a,int len,int opt) 
    { 
        for(int i=1;i<len;i<<=1) 
            for(int j=0;j<len;j+=i<<1) 
                for(int k=0;k<i;++k) 
                {
                    int x=a[j+k],y=a[j+k+i];        
                    a[j+k]=(ll)(x+y)%mod,a[j+k+i]=(ll)(x-y+mod)%mod;   
                    if(opt==-1) a[j+k]=(ll)inv2*a[j+k]%mod,a[j+k+i]=(ll)inv2*a[j+k+i]%mod;    
                }                        
    }            
    int main() 
    { 
        // setIO("input");        
        inv2=INV(2);   
        scanf("%d%d",&n,&m);   
        for(int i=1;i<=n+1;++i)  bin[i]=1<<(i-1);  
        for(int i=1;i<=m;++i) 
        {
            int x,y;
            scanf("%d%d",&x,&y);    
            mp[x][y]=mp[y][x]=1;   
        }        
        for(int S=1;S<bin[n+1];++S) 
        {   
            int fi;  
            for(int j=1;j<=n;++j) 
                if(S&bin[j]) { E[S]=E[S^bin[j]],fi=j; break; }
            size[S]=size[S^bin[fi]]+1;     
            for(int j=1;j<=n;++j) if(mp[fi][j]&&(S&bin[j])) ++E[S];           
        }              
        for(int i=1;i<bin[n+1];++i) 
        {  
            int d=(size[i]%2)==0?(mod-1):1;       
            g[size[i]][i]=(ll)d*INV(qpow(2,E[i]))%mod;         
        }    
        dp[0][0]=1;                          
        FWT(dp[0],bin[n+1],1);         
        for(int i=1;i<=n;++i) FWT(g[i],bin[n+1],1);            
        for(int sz=1;sz<=n;++sz) 
        {
            for(int i=1;i<=sz;++i)       
                for(int s=0;s<bin[n+1];++s) 
                    (dp[sz][s]+=(ll)g[i][s]*dp[sz-i][s]%mod)%=mod;   
        }
        FWT(dp[n],bin[n+1],-1);           
        printf("%d
    ",(ll)dp[n][bin[n+1]-1]*qpow(2,E[bin[n+1]-1])%mod*INV(qpow(3,E[bin[n+1]-1]))%mod); 
        return 0; 
    }     
    

      

  • 相关阅读:
    [转]SQL Server中的执行引擎入门
    [转]C# 导入导出Excel通用类(SamWang)
    【转】TSQL查询进阶—理解SQL Server中的锁
    [转载]使用分页方式读取超大文件的性能试验
    【总结】读《WEB三层架构的束缚》后的感想
    【转】jQuery使用 $.post提交json数据
    【原创】关于索引的总结
    【转】.net 匿名函数的变化
    【转】List<T>的Sort,Find,Exists等的使用
    【转】Http中Get/Post请求区别
  • 原文地址:https://www.cnblogs.com/guangheli/p/12822034.html
Copyright © 2011-2022 走看看