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

Problem

bzoj2560

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

Solution

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

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

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

根据定义可得

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

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

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

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

\(f(S)=g(S)-\sum_{T\subseteq 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\n",f[bin[n]-1]);
return 0;
}

最新文章

  1. XVI Open Cup named after E.V. Pankratiev. GP of Peterhof
  2. 【Bugly干货分享】微信文件微起底Ⅰ
  3. ZOJ 3903 Ant ZOJ Monthly, October 2015 - A
  4. Codeforces Round #260 (Div. 2) C
  5. SPOJ 1487 Query on a tree III(划分树)
  6. SAX - DefaultHandler
  7. html 笔记
  8. 使用FlashWavRecorder实现浏览器录制wav音频和上传音频文件,兼容IE8以上浏览器
  9. 下篇: php 微商城 基于Thinkphp3.2框架开发
  10. VBS 备份文件
  11. python request 库
  12. [No0000140]WMI使用的WIN32_类库名
  13. js几个小技巧和坑
  14. 5.2_k-means案例分析
  15. 转:Intellij idea Version Control File Status Colors ( 版本控制文件状态颜色 )
  16. Jenkins邮件通知
  17. 搜索评价指标——NDCG
  18. linux如何查看进程OOM killer
  19. PhpStorm 回到上次编辑位置的快捷键
  20. oracle客户端服务端字符集-解决乱码

热门文章

  1. tmux用法【常用】
  2. GIL 全局解释器
  3. 前端面试题整理—ES6篇
  4. vue实现简单的全选、反选、不选
  5. gcc 编译 汇编 链接
  6. 使用java poi解析表格
  7. SQL Server2012远程访问第二个实列
  8. 【Unity&amp;C#】lambda函数
  9. Filter 起航 编程式配置 压缩响应 日志过滤器
  10. 广度优先遍历(BFS )(转)