bzoj2560 串珠子
Description
现在已知所有珠子互不相同,用整数1到n编号。对于第i个珠子和第j个珠子,可以选择不用绳子连接,或者在ci,j根不同颜色的绳子中选择一根将它们连接。如果把珠子看作点,把绳子看作边,将所有珠子连成一个整体即为所有点构成一个连通图。特别地,珠子不能和自己连接。
铭铭希望知道总共有多少种不同的方案将所有珠子连成一个整体。由于答案可能很大,因此只需输出答案对1000000007取模的结果。
Input
标准输入。输入第一行包含一个正整数n,表示珠子的个数。接下来n行,每行包含n个非负整数,用空格隔开。这n行中,第i行第j个数为ci,j。
Output
标准输出。输出一行一个整数,为连接方案数对1000000007取模的结果。
Sample Input
0 2 3
2 0 4
3 4 0
Sample Output
HINT
对于100%的数据,n为正整数,所有的ci,j为非负整数且不超过1000000007。保证ci,j=cj,i。每组数据的n值如下表所示。
编号 1 2 3 4 5 6 7 8 9 10
n 8 9 9 10 11 12 13 14 15 16
正解:状压dp。
这道题很玄学,感觉还是懵懵懂懂。。今天的出题人太丧病了。。
考虑状压dp,我们把n个点压成二进制数。
我们设两个数组,g[s]表示s状态下的所有情况,即s状态下的点两两之间任意连边(包括不连边的情况),f[s]表示s状态下的合法情况,即使得s状态下所有点连通的合法情况。那么答案就是f[2^n-1]。
然后我们可以很容易地求出g[s],我们求出g[s]后,考虑如何求f[s],f[s]就是g[s]减去所有的不合法情况。那么我们可以枚举s的所有子集,设子集为i,那么不合法的情况就是g[i]*f[s^i],我们减去这些情况,就能求出f[s]了。
枚举子集很玄学。。我反正不知道这是怎么回事,看了网上大神的博客。。
http://www.cnblogs.com/jffifa/archive/2012/01/16/2323999.html
for (int x = S; x; x = (x-)&S)
大概是这个鬼东西。。大神的证明:
x = (x-1)&S实际上是把S中的0全部忽略,并不断减1的结果,比如S=1011,则x分别为:1011, 1010, 1001, 1000, 0011, 0010, 0001。忽略S中第二位的0其实就是111, 110, 101, 100, 011, 010, 001。
称S中的1所在位为有效位,0所在位为无效位,则x中的无效位必为0,有效位为0或1,比如S=1011,x=1001(有效位加下划线)。-1就是加上-1补码1111…,可以想成把无效位的1先加上去,比如x=1001变成1101,再加有效位的1。由于无效位加完肯定是1,会把有效位的进位“传递”下去,然后再位与S使得无效位变成0,实际就相当于有效位加上1111…,也就是有效位-1。
于是我们就能解决这题了。其实我还没搞懂为什么要这么搞。
//It is made by wfj_2048~
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#define inf (1<<30)
#define il inline
#define RG register
#define ll long long
#define rhl 1000000007
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) using namespace std; ll f[<<],g[<<],bin[],a[][],n; il int gi(){
RG int x=,q=; RG char ch=getchar(); while ((ch<'' || ch>'') && ch!='-') ch=getchar();
if (ch=='-') q=-,ch=getchar(); while (ch>='' && ch<='') x=x*+ch-,ch=getchar(); return q*x;
} il void work(){
n=gi(),bin[]=;
for (RG int i=;i<=n;++i)
for (RG int j=;j<=n;++j) a[i][j]=gi();
for (RG int i=;i<=n;++i) bin[i]=bin[i-]<<;
for (RG int k=;k<bin[n];++k){
f[k]=;
for (RG int i=;i<n;++i) if (k&bin[i-])
for (RG int j=i+;j<=n;++j) if (k&bin[j-]) f[k]=f[k]*(a[i][j]+)%rhl;
g[k]=f[k]; RG int i=k^(k&-k); //枚举真子集?!
for (RG int j=i;j;j=(j-)&i) f[k]=(f[k]-g[j]*f[k^j]%rhl+rhl)%rhl;
}
printf("%lld\n",f[bin[n]-]); return;
} int main(){
File("bunch");
work();
return ;
}
bzoj2560 串珠子的更多相关文章
- bzoj2560串珠子 状压dp+容斥(?)
2560: 串珠子 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 515 Solved: 348[Submit][Status][Discuss] ...
- bzoj2560串珠子(子集dp)
铭铭有n个十分漂亮的珠子和若干根颜色不同的绳子.现在铭铭想用绳子把所有的珠子连接成一个整体. 现在已知所有珠子互不相同,用整数1到n编号.对于第i个珠子和第j个珠子,可以选择不用绳子连接,或者在ci, ...
- 题解-bzoj2560 串珠子
刚被教练数落了一通,心情不好,来写篇题解 Problem bzoj2560 题目简述:给定\(n\)个点的,每两个点\(i,j\)之间有\(c_{i,j}\)条直接相连的路(其中只能选一条或不选),问 ...
- BZOJ2560串珠子
/* 很清新的一道题(相比上一道题) g[S]表示该 S集合中胡乱连的所有方案数, f[S] 表示S集合的答案 那么F[S] 等于G[S]减去不合法的部分方案 不合法的方案就枚举合法的部分就好了 g[ ...
- 2019.02.09 bzoj2560: 串珠子(状压dp+简单容斥)
传送门 题意简述:nnn个点的带边权无向图,定义一个图的权值是所有边的积,问所有nnn个点都连通的子图的权值之和. 思路: fif_ifi表示保证集合iii中所有点都连通其余点随意的方案数. gig ...
- 【题解】Bzoj2560串珠子
挺强的……容斥+状压DP.首先想到如果可以求出f[k],f[k]代表联通状态为k的情况下的合法方案数,则f[k] = g[k] - 非法方案数.g[k]为总的方案数,这是容易求得的.那么非法方案数我们 ...
- bzoj2560串珠子——子集DP
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2560 转载: 很明显的状压dp 一开始写的dp可能会出现重复统计的情况 而且难以去重 假设 ...
- [BZOJ2560]串珠子:状压DP+容斥原理
分析 为什么我去年6月做过这道题啊,估计当时抄的题解. 具体做法就是令\(f[S]\)表示保证连通点集\(S\)的方案数,\(g[S]\)表示不保证连通点集\(S\)的方案数. 容易想到: \[g[S ...
- bzoj2560 串珠子 状压DP
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=2560 题解 大概是这类关于无向图的联通性计数的套路了. 一开始我想的是这样的,考虑容斥,那么就 ...
随机推荐
- Android OkHttp使用与分析
安卓开发领域,很多重要的问题都有了很好的开源解决方案,例如网络请求 OkHttp + Retrofit 简直就是不二之选."我们不重复造轮子不表示我们不需要知道轮子该怎么造及如何更好的造!& ...
- (30)批处理文件.bat
批处理文件(bat) 简单的说,批处理的作用就是自动的连续执行多条命令 .编写bat处理文件可以使用记事本的方式: 常见批处理文件的命令: echo 表示显示此命令后的字符 tiltle 设置窗口的标 ...
- (6)简单说说java中的线程
先甩出来两种创建线程的方法: private static int count = 100; public static void main(String[] args) { // 用继承Thread ...
- cssLoading效果
http://files.cnblogs.com/files/xdoudou/loaders.css-master.zip
- Android使用ADB命令和stetho查看app数据库
一.使用ADB命令查看 打开命令窗口,进入Android SDK目录下的platform-tools,执行命令: 1.输入:在windows下: adb shell 在linux下: ./adb sh ...
- java实现微信红包分配算法
红包算法分析 有人认为,抢红包的额度是从0.01到剩余平均值*N(N是一个系数,决定最大的红包值)之间,比如一共发了10块钱,发了10个红包:第一个人可以拿到(0.01~1*N)之间的一个红包值,当然 ...
- 任务调用及远端管理(基于Quartz.net)
这篇文章我们来了解一些项目中的一个很重要的功能:任务调度 可能有些同学还不了解这个,其实简单点说任务调度与数据库中的Job是很相似的东西 只不过是运行的物理位置与管理方式有点不一样,从功能上来说我觉得 ...
- JavaScript贪食蛇游戏制作详解
之前闲时开发过一个简单的网页版贪食蛇游戏程序,现在把程序的实现思路写下来,供有兴趣同学参考阅读. 代码的实现比较简单,整个程序由三个类,一组常量和一些游戏逻辑以外的初始化和控制代码组成,总共400多行 ...
- ceph集群安装
所有 Ceph 部署都始于 Ceph 存储集群.一个 Ceph 集群可以包含数千个存储节点,最简系统至少需要一个监视器和两个 OSD 才能做到数据复制.Ceph 文件系统. Ceph 对象存储.和 C ...
- 将一个对象push到数组之中的几点问题
在项目开发中我们需要向意数组中添加对象:首先想到的是利用数组的api,----push demo: var ar = [1,2,3] var ar2 = [11,22,33] var obj = { ...