【洛谷5492】[PKUWC2018] 随机算法(状压DP)
大致题意: 用随机算法求一张图的最大独立集:每次随机一个排列,从前到后枚举排列中的点,如果当前点加入点集中依然是独立集,就将当前点加入点集中,最终得到的点集就是最大独立集。求这个随机算法的正确率。
前言
\(PKUWC\)的题目就是妙啊。
题目很神仙,但看完题解后就很简单了,可这种东西像我这般蒟蒻根本想不到啊......
状压\(DP\)
设\(f_{i,j}\)表示当前已考虑过点集\(i\),最大独立集为\(j\)的方案数。
每次我们枚举一个不在点集中的点\(k\),设与其相邻的点的集合为\(a_k\)。
则,如果我们要选择点\(k\)作为独立集中的点,那么与其相邻的点就不能再选择,方便起见,我们直接把\(a_k\)算作考虑过的点。
即,对于\(f_{i,j}\)和\(k\),我们可以转移到\(f_{i|2^{k-1}|a_k,j+1}\)。
注,这里之所以是\(2^{k-1}\),因为我习惯用二进制下第\(x-1\)位来表示第\(x\)个数是否被选择。
不难发现,根据我们的转移方式,由于\(k\)不在点集中,所以点集中被选作独立集中的点的点一定不与\(k\)相邻,否则在那个点被选作独立集中的点时就已经把\(k\)加入点集了,因此必然\(j\)可以加\(1\)。
然后我们考虑,在这一步转移下,\(k\)肯定是要直接加入点集中的,即必然在剩下的点中名列第一,它的位置是固定的。
而对于那些与\(k\)相邻、又不在点集\(i\)中的点(即:\(a_k-(i\&a_k)\)),它们可以在\(k\)之后的任意一个位置(共有\(n-g_i-1\)个位置,其中\(g_i\)代表点集\(i\)中的点,\(1\)代表点\(k\))加入点集,因此方案数为\(A_{n-g_i-1}^{g_{a_k-(i\& a_k)}}\)。
其中,\(A\)表示排列数,\(A_n^m=\frac{n!}{(n-m)!}\);\(g_i\)表示点集\(i\)中点的个数。
所以:\(f_{i|2^{k-1}|a_k,j+1}+=f_{i,j}\cdot A_{n-g_i-1}^{g_{a_k-(i\&a_k)}}\)。
由于求概率,而我们求的是方案数,所以最后的答案就是:\(\frac{f_{2^n-1,w}}{n!}\),其中\(w\)表示最大独立集的大小。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 20
#define X 998244353
#define A(x,y) (1LL*Fac[x]*IFac[(x)-(y)]%X)
using namespace std;
int n,m,a[N+5],f[1<<N][N+5],g[1<<N],Fac[N+5],IFac[N+5];
I int Qpow(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
int main()
{
RI i,x,y;for(scanf("%d%d",&n,&m),i=1;i<=m;++i) scanf("%d%d",&x,&y),a[x]|=1<<y-1,a[y]|=1<<x-1;//读入,记录相邻点
for(Fac[0]=i=1;i<=N;++i) Fac[i]=1LL*Fac[i-1]*i%X;//预处理阶乘
for(IFac[N]=Qpow(Fac[N],X-2),i=N-1;~i;--i) IFac[i]=1LL*IFac[i+1]*(i+1)%X;//预处理阶乘逆元
RI j,k,t=1<<n;for(i=0;i^t;++i) g[i]=g[i>>1]+(i&1);for(f[0][0]=1,i=0;i^t;++i)//枚举点集
{
for(j=0;j<=g[i];++j) for(k=1;k<=n;++k) !((i>>k-1)&1)&&//一定要选择不在点集中的点
(f[i|(1<<k-1)|a[k]][j+1]=(1LL*f[i][j]*A(n-g[i]-1,g[a[k]-(i&a[k])])+f[i|(1<<k-1)|a[k]][j+1])%X);//转移
}
for(i=n;!f[t-1][i];--i);return printf("%d",1LL*f[t-1][i]*IFac[n]%X),0;//求最大独立集点数,然后输出答案
}
【洛谷5492】[PKUWC2018] 随机算法(状压DP)的更多相关文章
- LOJ2540 PKUWC2018 随机算法 状压DP
传送门 两种$DP$: ①$f_{i,j}$表示前$i$次选择,最大独立集为$j$时达到最大独立集的方案总数,转移:$a.f_{i,j}+=f_{i+1,j+2^k}$(保证$k$加入后符合条件):$ ...
- 【题解】洛谷P3959 [NOIP2017TG] 宝藏(状压DP+DFS)
洛谷P3959:https://www.luogu.org/problemnew/show/P3959 前言 NOIP2017时还很弱(现在也很弱 看出来是DP 但是并不会状压DP 现在看来思路并不复 ...
- 洛谷 P1278 单词游戏 【状压dp】
题目描述 Io和Ao在玩一个单词游戏. 他们轮流说出一个仅包含元音字母的单词,并且后一个单词的第一个字母必须与前一个单词的最后一个字母一致. 游戏可以从任何一个单词开始. 任何单词禁止说两遍,游戏中只 ...
- 洛谷P2051 [AHOI2009] 中国象棋(状压dp)
题目简介 n*m的棋盘,对每行放炮,要求每行每列炮数<=2,求方案数%9999973 N,M<=100 题目分析 算法考虑 考虑到N,M范围较小,每一行状态只与前面的行状态有关,考虑状压D ...
- 洛谷P2704 [NOI2001]炮兵阵地 [状压DP]
题目传送门 炮兵阵地 题目描述 司令部的将军们打算在N*M的网格地图上部署他们的炮兵部队.一个N*M的地图由N行M列组成,地图的每一格可能是山地(用“H” 表示),也可能是平原(用“P”表示),如下图 ...
- 洛谷P2761 软件补丁问题(状压DP,SPFA)
题意 描述不清... Sol 网络流24题里面怎么会有状压dp?? 真是狗血,不过还是简单吧. 直接用$f[sta]$表示当前状态为$sta$时的最小花费 转移的时候枚举一下哪一个补丁可以搞这个状态 ...
- 洛谷P2831 愤怒的小鸟——贪心?状压DP
题目:https://www.luogu.org/problemnew/show/P2831 一开始想 n^3 贪心来着: 先按 x 排个序,那么第一个不就一定要打了么? 在枚举后面某一个,和它形成一 ...
- 洛谷$P$3160 局部极小值 $[CQOI2012]$ 状压$dp$
正解:状压$dp$ 解题报告: 传送门! 什么神仙题昂,,,反正我是没有想到$dp$的呢$kk$,,,还是太菜了$QAQ$ 首先看数据范围,一个4×7的方格,不难想到最多有8个局部极小值,过于显然懒得 ...
- 洛谷P2761 软件补丁问题 [状压DP,SPFA]
题目传送门 软件补丁问题 题目描述 T 公司发现其研制的一个软件中有 n 个错误,随即为该软件发放了一批共 m 个补丁程序.每一个补丁程序都有其特定的适用环境,某个补丁只有在软件中包含某些错误而同时又 ...
- 洛谷 P2473 [SCOI2008]奖励关(状压dp+期望)
题面 luogu 题解 \(n \leq 15\) 状压 \(f[i][S]\)表示第\(i\)轮,吃过的集合为\(S\) 正着转移好像有点复杂 考虑逆推转移(正着转移应该也行) \(f[i][S]\ ...
随机推荐
- 【Spring MVC】Properties文件的加载
[Spring MVC]Properties文件的加载 转载:https://www.cnblogs.com/yangchongxing/p/10726885.html 参考:https://java ...
- 【玩转SpringBoot】给自动配置来个整体大揭秘
上一篇文章中提到的条件注解,只是自动配置整体解决方案中的一个环节而已,可以说是管中窥豹. 本文就逐步擦除迷雾,让整体浮现出来,这样就会有一个宏观的认识. 除了写代码之外,还能干点什么? 提到“配置”这 ...
- Python3之Django的Cookie与Session的使用
一.Cookie的使用 1.设置Cookie url.set_cookie("tile","zhanggen",expires=value,path='/' ) ...
- 输出错误long类型
Microsoft Visual C++ 输出不了long 类型的数字怎么办? 在C/C++中,64为整型一直是一种没有确定规范的数据类型.现今主流的编译器中,对64为整型的支持也是标准不一,形态各异 ...
- 《Java基础知识》Java变量作用域
对于在作用域里定义的变量,作用域同时决定了它的“可见性”以及“存在时间”.在JAVA里,作用域是由花括号的位置决定的.JAVA用一对大括号作为语句块的范围,称为作用域,在作用域里定义的变量,只有在该作 ...
- 浅析堆栈段,BBS段,数据段,代码段
文章目录 1. 进程,线程 2. 堆栈段 3. BBS段 4. 代码段 5. 数据段 6. 例子 7. 总结 1. 进程,线程 所谓进程是指在系统中能独立运行并作为资源分配的基本单位,程序段,数据段和 ...
- 如何"快准狠"找到内存相关的问题
为了迅速定位内存问题,通常会先运行几个覆盖面比较大的性能工具,比如 free.top.vmstat.pidstat 等. 具体的分析思路主要有这几步 先用 free 和 top,查看系统整体的内存使用 ...
- Nginx配置实例-负载均衡实例:平均访问多台服务器
场景 Nginx配置实例-反向代理实例:根据访问的路径跳转到不同端口的服务中: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/10 ...
- [UIApplication sharedApplication].keyWindow和[[UIApplication sharedApplication].delegate window]区别
参考链接:https://www.cnblogs.com/henusyj-1314/p/11643189.html 结论1.在获取到window时最好使用[[UIApplication sharedA ...
- DDMS files not found: xxx\hprof-conv.exe
出现如下错误: DDMS files not found: xxx\hprof-conv.exe The connection to adb is down, and a severe error h ...