zoukankan      html  css  js  c++  java
  • uoj#37. 【清华集训2014】主旋律(状压dp+容斥)

    传送门

    第一眼容斥,然后我就死活容不出来了……

    (f_i)为点集(i)中的点强联通的方案数,那么就是总的方案数减去使(i)不连通的方案数

    如果(i)不连通的话,我们可以枚举缩点之后拓扑序最小(也就是入度为(0))的强连通分量,然而这种强联通分量可能不止一个,需要容斥,不难发现这里的容斥系数在强联通分量个数为奇数时为正,为偶数时为负(也就是强联通分量为奇数时要减掉方案数,为偶数时要加上方案数)

    (g_i)为点集(i)中形成奇数个强连通分量的方案数(-)形成偶数个强联通分量的方案数,设这个点集中编号最小的点为(x),我们枚举与(x)在同一强连通分量中的点集(j),容斥可得(g_i=-sum_{jsubset x}f_{i-j}g_j),注意这里不包含(g)只有一个强联通分量的方案数

    然后我们钦定一下入度为(0)的强联通分量(j),则有转移(f_i=2^{sum_i}-sumlimits_{jsubset i}2^{sum_i-w_j} imes g_j),其中(sum[i])为点集(i)中的边数,(w_j)(i)(j)连边的数目,就是说这些钦定的点连不出来

    最后把(f_i)(g_i)加上去,代表(g)只有一个强联通分量的方案数

    //minamoto
    #include<bits/stdc++.h>
    #define R register
    #define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
    #define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
    #define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
    using namespace std;
    char buf[1<<21],*p1=buf,*p2=buf;
    inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
    int read(){
        R int res,f=1;R char ch;
        while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
        for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
        return res*f;
    }
    char sr[1<<21],z[20];int C=-1,Z=0;
    inline void Ot(){fwrite(sr,1,C+1,stdout),C=-1;}
    void print(R int x){
        if(C>1<<20)Ot();if(x<0)sr[++C]='-',x=-x;
        while(z[++Z]=x%10+48,x/=10);
        while(sr[++C]=z[Z],--Z);sr[++C]='
    ';
    }
    const int N=(1<<15)+5,P=1e9+7;
    inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
    inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
    inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
    int ksm(R int x,R int y){
    	R int res=1;
    	for(;y;y>>=1,x=mul(x,x))if(y&1)res=mul(res,x);
    	return res;
    }
    int in[N],out[N],sz[N],sum[N],w[N],f[N],g[N],bin[225];
    int n,m,u,v,lim,S;
    void dfs(int i,int j){
    	if(i&(j-1))dfs(i,i&(j-1));
    	w[j]=w[j-(j&-j)]+sz[in[j&-j]&i];
    }
    int main(){
    //	freopen("testdata.in","r",stdin);
    	n=read(),m=read(),bin[0]=1,lim=(1<<n);
    	fp(i,1,m)bin[i]=mul(bin[i-1],2);
    	fp(i,1,m)u=read()-1,v=read()-1,in[1<<v]|=(1<<u),out[1<<u]|=(1<<v);
    	fp(i,1,lim){
    		S=i-(i&-i),sz[i]=sz[S]+1,sum[i]=sum[S]+sz[in[i&-i]&i]+sz[out[i&-i]&i],f[i]=bin[sum[i]];
    		dfs(i,i);
    		for(R int j=S;j;j=(j-1)&S)g[i]=dec(g[i],mul(f[i^j],g[j]));
    		for(R int j=i;j;j=(j-1)&i)f[i]=dec(f[i],mul(bin[sum[i]-w[j]],g[j]));
    		g[i]=add(g[i],f[i]);
    	}
    	printf("%d
    ",f[lim-1]);
    	return 0;
    }
    
  • 相关阅读:
    在 Windows 上测试 Redis Cluster的集群填坑笔记
    vmware安装黑苹果教程
    微信支付v3发布到iis时的证书问题
    Linux下安装SQL Server 2016(连接篇SQL Server on linux)
    Linux下安装SQL Server 2016(连接篇SQL Server on linux)
    Linux下安装SQL Server 2016(安装篇SQL Server on linux)
    Linux下安装SQL Server 2016(准备篇SQL Server on linux)
    客服端与服务端APP支付宝支付接口联调的那些坑
    ASP.NET MVC]WebAPI应用支持HTTPS的经验总结
    .net平台下C#socket通信(中)
  • 原文地址:https://www.cnblogs.com/bztMinamoto/p/10243690.html
Copyright © 2011-2022 走看看