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;
    }
    
  • 相关阅读:
    5-1 CSS命名规范
    npm
    Maven的安装与配置
    Emmet
    计算机常识——IP/TCP协议
    判别分析——距离判别
    R语言创建空向量、矩阵
    Rstudio——基本功能及操作
    R语言——source函数
    R语言关于warning问题——关于options函数
  • 原文地址:https://www.cnblogs.com/dixiao/p/15094439.html
Copyright © 2011-2022 走看看