[tsinsen_A1278]串珠子

试题描述

铭铭有 \(n\) 个十分漂亮的珠子和若干根颜色不同的绳子。现在铭铭想用绳子把所有的珠子连接成一个整体。

现在已知所有珠子互不相同,用整数 \(1\) 到 \(n\) 编号。对于第 \(i\) 个珠子和第 \(j\) 个珠子,可以选择不用绳子连接,或者在 \(c_{i,j}\) 根不同颜色的绳子中选择一根将它们连接。如果把珠子看作点,把绳子看作边,将所有珠子连成一个整体即为所有点构成一个连通图。特别地,珠子不能和自己连接。

铭铭希望知道总共有多少种不同的方案将所有珠子连成一个整体。由于答案可能很大,因此只需输出答案对 \(1000000007\) 取模的结果。

输入

标准输入。输入第一行包含一个正整数 \(n\),表示珠子的个数。接下来 \(n\) 行,每行包含 \(n\) 个非负整数,用空格隔开。这 \(n\) 行中,第 \(i\) 行第 \(j\) 个数为 \(c_{i,j}\)。

输出

标准输出。输出一行一个整数,为连接方案数对 \(1000000007\) 取模的结果。

输入示例

3
0 2 3
2 0 4
3 4 0

输出示例

50

数据规模及约定

对于 \(100\%\) 的数据,\(n\) 为正整数,所有的 \(c_{i,j}\) 为非负整数且不超过 \(1000000007\)。保证 \(c_{i,j}=c_{j,i}\)。每组数据的 \(n\) 值如下表所示。

编号 1 2 3 4 5 6 7 8 9 10
$n$ $8$ $9$ $9$ $10$ $11$ $12$ $13$ $14$ $15$ $16$

题解

一道挺经典的状压 dp,这题有一些计数技巧。

状态很简单,就是令 \(f(s)\) 表示集合 \(s\) 内所有点处于一个连通分量内的方案数,关键是怎么转移。

为了让计算的方案不重不漏,我们需要设计一个方案使得每次转移都是唯一的,不会被重复转移,同时也能够让转移覆盖到所有情况。

这题就是找到集合 \(s\) 中的前两个元素(或者第一个和最后一个元素也行,需要保证每次都选的是特定的两个元素),令第一个为 \(t_1\),第二个为 \(t_2\),然后我们要枚举第一次拆解(这次拆解后的两个集合都通过 \(t_1\) 这个点相连,即 \(t_1\) 是 \(s\) 连通分量的割顶),并且由于这个拆解是没有顺序的,所以我们要保证每次拆解都需要将 \(t_1\) 和 \(t_2\) 分开。于是枚举 \(s\) 的子集 \(s'\),使得 \(t_2 \in s'\) 且 \(t_1 \in s - s'\),然后将 \(s\) 分成 \(s'\) 和 \(s - s'\) 两个集合,最后转移就是 \(f(s) = f(s') \cdot f(s-s') \cdot \prod_{i \in s'} {c_{t_1, i}}\)。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
using namespace std;
#define rep(i, s, t) for(int i = (s); i <= (t); i++)
#define dwn(i, s, t) for(int i = (s); i >= (t); i--) const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *Tail;
inline char Getchar() {
if(Head == Tail) {
int l = fread(buffer, 1, BufferSize, stdin);
Tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 20
#define maxs 65536
#define MOD 1000000007
#define LL long long int n, c[maxn][maxn], Log[maxs], f[maxs], mul[maxn][maxs]; int main() {
n = read();
rep(i, 0, n - 1) rep(j, 0, n - 1) c[i][j] = read(); int all = (1 << n) - 1;
Log[1] = 0;
rep(i, 2, all + 1) Log[i] = Log[i>>1] + 1;
rep(i, 0, n - 1) {
mul[i][0] = 1;
rep(s, 1, all) mul[i][s] = (LL)mul[i][s&~(s&-s)] * (c[i][Log[s&-s]] + 1) % MOD;
}
rep(s, 1, all) {
int cnt = 0, t1 = -1, t2 = -1;
rep(i, 0, n - 1) if(s >> i & 1) {
cnt++;
if(t1 < 0) t1 = i;
else if(t2 < 0) t2 = i;
}
if(cnt == 1){ f[s] = 1; continue; }
for(int ts = (s - 1 & s); ts; ts = (ts - 1 & s)) if((ts >> t2 & 1) && !(ts >> t1 & 1)) {
f[s] += (LL)f[ts] * f[s^ts] % MOD * (mul[t1][ts] + MOD - 1) % MOD;
if(f[s] >= MOD) f[s] -= MOD;
}
} printf("%d\n", f[all]); return 0;
}

[tsinsen_A1278]串珠子的更多相关文章

  1. bzoj2560串珠子 状压dp+容斥(?)

    2560: 串珠子 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 515  Solved: 348[Submit][Status][Discuss] ...

  2. 【BZOJ2560】串珠子 状压DP+容斥

    [BZOJ2560]串珠子 Description 铭铭有n个十分漂亮的珠子和若干根颜色不同的绳子.现在铭铭想用绳子把所有的珠子连接成一个整体. 现在已知所有珠子互不相同,用整数1到n编号.对于第i个 ...

  3. BZOJ 2560: 串珠子 (状压DP+枚举子集补集+容斥)

    (Noip提高组及以下),有意者请联系Lydsy2012@163.com,仅限教师及家长用户. 2560: 串珠子 Time Limit: 10 Sec Memory Limit: 128 MB Su ...

  4. bzoj2560 串珠子

    Description 铭铭有n个十分漂亮的珠子和若干根颜色不同的绳子.现在铭铭想用绳子把所有的珠子连接成一个整体. 现在已知所有珠子互不相同,用整数1到n编号.对于第i个珠子和第j个珠子,可以选择不 ...

  5. bzoj 2560: 串珠子

    Description 铭铭有n个十分漂亮的珠子和若干根颜色不同的绳子.现在铭铭想用绳子把所有的珠子连接成一个整体. 现在已知所有珠子互不相同,用整数1到n编号.对于第i个珠子和第j个珠子,可以选择不 ...

  6. BSOJ 4062 -- 【清华集训2012】串珠子

    Description 铭铭有n个十分漂亮的珠子和若干根颜色不同的绳子.现在铭铭想用绳子把所有的珠子连接成一个整体. 现在已知所有珠子互不相同,用整数1到n编号.对于第i个珠子和第j个珠子,可以选择不 ...

  7. bzoj2560串珠子(子集dp)

    铭铭有n个十分漂亮的珠子和若干根颜色不同的绳子.现在铭铭想用绳子把所有的珠子连接成一个整体. 现在已知所有珠子互不相同,用整数1到n编号.对于第i个珠子和第j个珠子,可以选择不用绳子连接,或者在ci, ...

  8. 【bzoj2560】串珠子 状压dp+容斥原理

    题目描述 有 $n$ 个点,点 $i$ 和点 $j$ 之间可以连 $0\sim c_{i,j}$ 条无向边.求连成一张无向连通图的方案数模 $10^9+7$ .两个方案不同,当且仅当:存在点对 $(i ...

  9. 【BZOJ2560】串珠子(状压DP,容斥原理)

    题意: 铭铭有n个十分漂亮的珠子和若干根颜色不同的绳子.现在铭铭想用绳子把所有的珠子连接成一个整体.现在已知所有珠子互不相同,用整数1到n编号.对于第i个珠子和第j个珠子,可以选择不用绳子连接,或者在 ...

随机推荐

  1. GB MB KB B 关系

    1KB=1024Bytes=2的10次方Bytes 1MB=1024KB=2的20次方Bytes 1GB=1024MB=2的30次方Bytes 1TB=1024GB=2的40次方Bytes

  2. XGBoost算法原理小结

    在两年半之前作过梯度提升树(GBDT)原理小结,但是对GBDT的算法库XGBoost没有单独拿出来分析.虽然XGBoost是GBDT的一种高效实现,但是里面也加入了很多独有的思路和方法,值得单独讲一讲 ...

  3. 解决MySQL安装到最后一步未响应的三种方法

    这种情况一般是你以前安装过MySQL数据库服务项被占用了.解决方法: 方法一:安装MySQL的时候在这一步时它默认的服务名是“MySQL” 只需要把这个名字改了就可以了.可以把默认的服务器的名称手动改 ...

  4. java链接MySQL数据库时使用com.mysql.jdbc.Connection的包会出红线问题 java.lang.ClassNotFoundException: com.mysql.jdbc.Driver问题

    package com.swift; //这里导入的包是java.sql.Connection而不是com.mysql.jdbc.Connection import java.sql.Connecti ...

  5. 关于JavaScript中的事件代理(例子:ul中无数的li上添加点击事件)

    面试题:一个ul中有一千个li,如何给这一千个li绑定一个鼠标点击事件,当鼠标点击时alert出这个li的内容和li的位置坐标xy. 看到这个题目,我们一般首先想到的思路是,for循环,遍历1000次 ...

  6. jquery实现全选、取消反选、加JavaScript三元运算(三种法法实现反选)

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  7. sql 参数化查询

      在初次接触sql时,笔者使用的是通过字符串拼接的方法来进行sql查询,但这种方法有很多弊端 其中最为明显的便是导致了sql注入. 通过特殊字符的书写,可以使得原本正常的语句在sql数据库里可编译, ...

  8. GNU汇编程序框架

    汇编的作用:1.对芯片进行初始化 2. 和C混合编程提升C的运行效率 .section .data < 初始化的数据> .section .bss <未初始化的数据> .sec ...

  9. 本地已经存在的项目如何跟github发生关联

    切换到本地项目地址 git init 初始化项目.该步骤会创建一个 .git文件夹是附属于该仓库的工作树. git add . git commit -am 'initial commit' git ...

  10. nuxt.js服务端缓存lru-cache

    对于部分网页进行服务端的缓存,可以获得更好的渲染性能,但是缓存又涉及到一个数据的及时性的问题,所以在及时性和性能之间要有平衡和取舍. 官方文档里面写的使用方法 按照这个配置,试过了没什么用,但是从文档 ...