zoukankan      html  css  js  c++  java
  • [清华集训2012]串珠子

    是一个很经典集合问题。
    在一个点集中,一定可以分割成若干个联通子集。
    如果我们设 \(f_i\) 为一个点集的联通方案,\(g_i\) 为一个点集的所有方案。
    我们先任取一个点,考虑枚举一个集合和这个点不联通。
    那么我们知道这样不连通的方案 \(\sum g[j] \times\ f[i\ xor\ j]\)
    依据简单的容斥:
    \(f_i = g_i - \sum_{s\in(i\ xor\ j)}\ g[j] \times\ f[i\ xor\ j]\)
    答案为 \(f_{2^n - 1}\)

    在实现有细节,即先把当前集合丢掉 \(lowbit(i)\),在枚举不连通的子集。

    #include<iostream>
    #include<cstdio>
    #define ll long long 
    #define mod 1000000007
    #define N 20
    #define M (1 << 17)
    
    ll n;
    
    ll c[N][N];
    
    ll f[M],g[M];
    
    int main(){
    	scanf("%lld",&n);
    	for(int i = 1;i <= n;++i)
    	for(int j = 1;j <= n;++j)
    	scanf("%lld",&c[i - 1][j - 1]);
    	ll K = (1 << n) - 1;
    	for(int i = 0;i <= K;++i){
    		g[i] = 1;
    		for(int j = 0;j <= n - 1;++j){
    			for(int k = j + 1;k <= n - 1;++k){
    				if(((i >> j) & 1) && ((i >> k) & 1))
    				g[i] = (g[i] * (c[j][k] + 1)) % mod;
    			}
    		}
    	}
    	for(int i = 0;i <= K;++i){
    		f[i] = g[i];
    		int t = i ^ (i & -i);
    		for(int j = t;j > 0;j = (j - 1) & t){
    			f[i] = (f[i] - g[j] * f[i ^ j] % mod + mod) % mod;
    		}
    	}
    	std::cout<<f[K]<<std::endl;
    }
    
  • 相关阅读:
    OKHttp的使用
    多点触控
    事件分发机制的理解
    Activity的四种启动模式
    反射动态建表
    px,dp,sp三者的转换
    动态广播和静态广播的区别
    字符串转日期格式
    hive Metastore contains multiple versions
    记一次 qW3xT.4,解决挖矿病毒。
  • 原文地址:https://www.cnblogs.com/dixiao/p/15094439.html
Copyright © 2011-2022 走看看