LOJ2540 [PKUWC2018] 随机算法 【状压DP】
题目分析:
听说这题考场上能被$ O(4^n) $的暴力水过,难不成出题人是毕姥爷?
首先思考一个显而易见的$ O(n^2*2^n) $的暴力DP。一般的DP都是考虑最近的加入了哪个点,然后删除后递归进行状压DP。由于这道题的题目询问方式是反过来的,处理方式也反过来。
令$ f[n][S] $表示当前有$ S $这些点,期望这些点能够构成独立集大小为$ n $。正向的考虑选择了哪个点,并把与这个点有连边的所有点在集合内进行删除,令找到的新状态为$ f[n-1][P] $。我们把$ P $中的结点与$ S $中不在$ P $中的点进行标号拼接。写成语言就是$ f[n][S]+=f[n-1][P] * \binom{|S|-1}{|P|} * |P|! $ 由于对于$ S $的每一个点都需要转移一遍,时间复杂度就变成了$ O(n^2*2^n) $。虽然跑得不快,但是由于冗余状态较多,考场上一定比例的人使用这个算法通过了这个题。
现在来考虑把它优化到$ O(n*2^n) $。由于题目期望着你获得一个最大独立集,所以我们可以发现第一维是没有必要的。因为对于一个目标状态$ S $,我们如果知道$ S $对应的最大独立集的大小的话,那么我们必定是奔着这个大小而去的。现在我们用$ g[S] $来表示$ S $对应的最大独立集大小,那么这是一个普及组题目,枚举选点然后求max就行了。再对于$ f[S] $,求$ S $对应的最大独立集大小。首先记录$ g[S] $,然后找删除某个点后的集合变为了$ g[S]-1 $的就是我们想要的转移方案,同样采用带标号的拼接。因为我们没有了第一维的负担,所以时间复杂度骤降为了$ O(n*2^n) $.
ps:我终于会用letax数学公式啦。
代码:
#include<bits/stdc++.h>
using namespace std; const int maxn = ;
const int mod = ; int n,m;
int connect[maxn];
int f[(<<)+],g[(<<)+],sz[(<<)+];
int arr[(<<)+],C[maxn][maxn],fac[]; int fast_pow(int now,int pw){
if(pw == ) return now;
int z = fast_pow(now,pw/);
z = (1ll*z*z) % mod;
if(pw & ) z = (1ll*z*now)%mod;
return z;
} void read(){
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++){
int u,v; scanf("%d%d",&u,&v);
connect[u] |= (<<v-);
connect[v] |= (<<u-);
}
for(int i=;i<=n;i++) connect[i] |= (<<i-);
} void init(){
C[][] = ;
for(int i=;i<=n;i++){
C[i][] = C[i][i] = ;
for(int j=;j<i;j++) C[i][j] = (C[i-][j-]+C[i-][j])%mod;
}
for(int i=;i<(<<n);i++){
for(int j=;j<n;j++) if((<<j)&i) sz[i]++;
}
fac[] = ;
for(int i=;i<=n;i++) fac[i] = (1ll*fac[i-]*i)%mod;
} void dfs(int now){
arr[now] = ;
for(int i=;i<=n;i++){
if(!((<<i-)&now)) continue;
int p = now - (now&connect[i]);
if(!arr[p]) dfs(p);
g[now] = max(g[now],g[p]+);
}
} void dfs2(int now){
arr[now] = ;
for(int i=;i<=n;i++){
if(!((<<i-)&now)) continue;
int kk = (now&connect[i]),p = now - kk;
if(g[p] != g[now]-) continue;
if(!arr[p]) dfs2(p);
f[now]+=((1ll*C[sz[now]-][sz[p]]*fac[sz[kk]-])%mod)*f[p]%mod;
f[now] %= mod;
}
} void work(){
init();
g[] = ; arr[] = ;
for(int i=;i<(<<n);i++) if(!arr[i]) dfs(i);
memset(arr,,sizeof(arr));
f[] = ; arr[] = ;
dfs2((<<n)-);
int ans = f[(<<n)-];
ans = (1ll*fast_pow(fac[n],mod-)*ans)%mod;
printf("%d",ans);
} int main(){
read();
work();
return ;
}
LOJ2540 [PKUWC2018] 随机算法 【状压DP】的更多相关文章
- LOJ2540 PKUWC2018 随机算法 状压DP
传送门 两种$DP$: ①$f_{i,j}$表示前$i$次选择,最大独立集为$j$时达到最大独立集的方案总数,转移:$a.f_{i,j}+=f_{i+1,j+2^k}$(保证$k$加入后符合条件):$ ...
- [LOJ2540] [PKUWC2018] 随机算法
题目链接 LOJ:https://loj.ac/problem/2540 Solution 写的时候脑子不太清醒码了好长然后时间\(LOJ\)垫底... 反正随便状压\(dp\)一下就好了,设\(f[ ...
- 洛谷 P4547 & bzoj 5006 随机二分图 —— 状压DP+期望
题目:https://www.luogu.org/problemnew/show/P4547 https://www.lydsy.com/JudgeOnline/problem.php?id=5006 ...
- loj2540 「PKUWC2018」随机算法 【状压dp】
题目链接 loj2540 题解 有一个朴素三进制状压\(dp\),考虑当前点三种状态:没考虑过,被选入集合,被排除 就有了\(O(n3^{n})\)的转移 但这样不优,我们考虑优化状态 设\(f[i] ...
- 【洛谷5492】[PKUWC2018] 随机算法(状压DP)
点此看题面 大致题意: 用随机算法求一张图的最大独立集:每次随机一个排列,从前到后枚举排列中的点,如果当前点加入点集中依然是独立集,就将当前点加入点集中,最终得到的点集就是最大独立集.求这个随机算法的 ...
- 「算法笔记」状压 DP
一.关于状压 dp 为了规避不确定性,我们将需要枚举的东西放入状态.当不确定性太多的时候,我们就需要将它们压进较少的维数内. 常见的状态: 天生二进制(开关.选与不选.是否出现--) 爆搜出状态,给它 ...
- 算法笔记-状压dp
状压dp 就是把状态压缩的dp 这样还是一种暴力但相对于纯暴力还是优雅的多. 实际上dp就是经过优化的暴力罢了 首先要了解位运算 给个链接吧 [https://blog.csdn.net/u01337 ...
- Luogu4547 THUWC2017 随机二分图 概率、状压DP
传送门 考虑如果只有$0$组边要怎么做.因为$N \leq 15$,考虑状压$DP$.设$f_i$表示当前的匹配情况为$i$时的概率($i$中$2^0$到$2^{N-1}$表示左半边的匹配情况,$2^ ...
- 算法复习——状压dp
状压dp的核心在于,当我们不能通过表现单一的对象的状态来达到dp的最优子结构和无后效性原则时,我们可能保存多个元素的有关信息··这时候利用2进制的01来表示每个元素相关状态并将其压缩成2进制数就可以达 ...
随机推荐
- 10-(基础入门篇)MQTT介绍
https://www.cnblogs.com/yangfengwu/p/9953920.html 看到这个项目第一想法肯定需要一个服务器,所有的wifi设备和手机都去连接这个服务器,然后服务器进行信 ...
- Luogu3067 平衡的奶牛群 Meet in the middle
题意:给出$N$个范围在$[1,10^8]$内的整数,问有多少种取数方案使得取出来的数能够分成两个和相等的集合.$N \leq 20$ 发现爆搜是$O(3^N)$的,所以考虑双向搜索. 先把前$3^\ ...
- C#去除字符串中的反斜杠
如下,可以使用C#的Replace()方法来替换,但有一点需要注意的是backslash(反斜杠)是特殊字符. string s = "[\"aaaaaaaaaaaaaaaaaaa ...
- nginx 安装问题
yum -y install xxx pcre-devel openssl-devel zlib-devel 这个三个包需要 有时候,我们需要单独安装nginx,来处理大量的下载请求.单独在 ...
- EZ 2018 05 20 NOIP2018 模拟赛(十五)
这次的比赛充满着玄学的气息,玄学链接 首先讲一下为什么没有第十四场 其实今天早上9点时看到题目就叫了:原题! 没错,整套试卷都做过,我还写了题解 然后老叶就说换一套,但如果仅仅是这样就没什么 但等13 ...
- 2017NOIP游记
记得去年这个时候,大概刚接触OI.没想到时间这么快,第一次2017NOIP之旅已经结束.初测成绩出来了,100+100+95+50=345,有浙江三十几名(@Cptraser 机房370大佬).总体感 ...
- [Oracle]In-Memory的Join Group 位于内存的何处?
In-Memory的Join Group 的数据字典位于内存的何处? 有客户问到,使用Oracle 的In-Memory功能时,如果用到了 Join Group,那么这些这些Join Group,位于 ...
- Nginx Windows版的服务安装和管理工具
以前研究过负载均衡,最近正在项目上实施(从来没做过小项目以上级别的东西,哈),nginx挺好,不过Windows有点为难,小流量和本地不追求性能,简单易用是目标. Nginx Windows上并没有提 ...
- Azure Load Balancer : 支持 IPv6
越来越多的网站开始支持 IPv6,即使是哪些只提供 api 服务的站点也需要支持 IPv6,比如苹果应用商店中的 app 早就强制要求服务器端支持 IPv6 了.笔者在前文<Azure Load ...
- 树莓派3代b型静态IP设置,和ssh的wlan配置
https://blog.csdn.net/qq_36305492/article/details/78607557