zoukankan      html  css  js  c++  java
  • 题解-bzoj2560 串珠子

    刚被教练数落了一通,心情不好,来写篇题解

    Problem

    bzoj2560

    题目简述:给定(n)个点的,每两个点(i,j)之间有(c_{i,j})条直接相连的路(其中只能选一条或不选),问共有多少种方案可以使得整张图连通。(nleq 16)

    Solution

    算是遇到的没那么套路的容斥题了 虽然还是有点套路

    发现(nleq 16)各种暗示我们要状压,于是按照以往状压的题的套路,设(f(S))表示当(S)集合中的点连通方案数

    发现不是很好直接计算,但总方案数又很好得出,于是考虑容斥,设(g(S))表示集合(S)中的点之间随意相连的方案数

    根据定义可得

    [g(S)=prod_{i,jin S}(c_{i,j}+1) ]

    想法用(g)去消掉(f)不满足题意的方案数,联想到城市规划中的做法:限定(1)号节点的连通集合大小

    类似的,这里可以限定(S)中编号最小的点连通大小(当然编号最大的点也行)

    枚举(S)中编号最小的点连通块大小,可以得到(设(H)为集合(S)中去除最小元素的集合):

    (f(S)=g(S)-sum_{Tsubseteq H}g(T)f(S-T))

    题目之间类比关系好多啊,比如上一篇就是二项堆和AC自动机的类比

    Code

    #include <cstdio>
    const int N=18,M=1<<N,p=1e9+7;
    int g[M],f[M],bin[N];
    int a[N][N],n;
    
    inline int qm(int x){return x<p?x:x-p;}
    
    int main(){
    	scanf("%d",&n);
    	for(int i=0;i<n;++i)
    	for(int j=0;j<n;++j)
    		scanf("%d",&a[i][j]);
    	bin[0]=1;
    	for(int i=1;i<=n;++i)bin[i]=bin[i-1]<<1;
    	for(int S=0,s;S<bin[n];++S){
    		f[S]=1;
    		for(int i=0;i<n;++i)if(bin[i]&S)
    		for(int j=i+1;j<n;++j)if(bin[j]&S)
    			f[S]=1ll*f[S]*(a[i][j]+1)%p;
    		g[S]=f[S],s=(S-1)&S;
    		for(int i=s;i;i=(i-1)&s)
    			f[S]=qm((int)f[S]-1ll*g[i]*f[S^i]%p+p);
    	}
    	printf("%d
    ",f[bin[n]-1]);
    	return 0;
    }
    
  • 相关阅读:
    JFreeChart学习笔记
    Java基于JavaMail实现向QQ邮箱发送邮件遇到的问题
    JBPM入门
    eclipse jbmp 4.4 插件的安装及配置
    Redis开启远程登录连接
    springmvc @ResponseBody返回json 报406 not acceptable
    generatorConfiguration配置详解
    WCF、WebAPI、WCFREST、WebService之间的区别
    理解nodejs和react之间的关系
    DB2 sqlCode-668
  • 原文地址:https://www.cnblogs.com/penth/p/10153075.html
Copyright © 2011-2022 走看看