传送门


两种$DP$:

①$f_{i,j}$表示前$i$次选择,最大独立集为$j$时达到最大独立集的方案总数,转移:$a.f_{i,j}+=f_{i+1,j+2^k}$(保证$k$加入后符合条件);$b.f_{i,j}+=f_{i+1,j} \times \text{现在可以放的不影响最大独立集的点的数量}$,这个现在可以放的不影响最大独立集的点的数量就是不可选择的点(即已经选择和与已经选择的点相邻的点)的数量$-i$

复杂度$O(2^nn^2)$而且似乎无法优化

 #include<bits/stdc++.h>
//This code is written by Itst
using namespace std; inline int read(){
int a = ;
bool f = ;
char c = getchar();
while(c != EOF && !isdigit(c)){
if(c == '-')
f = ;
c = getchar();
}
while(c != EOF && isdigit(c)){
a = (a << ) + (a << ) + (c ^ '');
c = getchar();
}
return f ? -a : a;
} const int MOD = ;
bool can[][ << ] , edge[][] , choose[];
int dp[][ << ] , cnt1[ << ] , N , M , maxN , logg2[ << ]; inline int poww(long long a , int b){
int times = ;
while(b){
if(b & )
times = times * a % MOD;
a = a * a % MOD;
b >>= ;
}
return times;
} void dfs(int now , int size){
if(N - now + size <= maxN)
return;
if(now == N){
maxN = size;
return;
}
dfs(now + , size);
for(int i = ; i < now ; ++i)
if(choose[i] && edge[i][now])
return;
choose[now] = ;
dfs(now + , size + );
choose[now] = ;
} int main(){
#ifndef ONLINE_JUDGE
freopen("2540.in" , "r" , stdin);
//freopen("2540.out" , "w" , stdout);
#endif
N = read();
logg2[] = -;
for(int i = ; i < ( << N) ; ++i){
cnt1[i] = cnt1[i - (i & -i)] + ;
logg2[i] = logg2[i >> ] + ;
}
for(M = read() ; M ; --M){
int a = read() - , b = read() - ;
edge[a][b] = edge[b][a] = ;
}
dfs( , );
for(int i = ; i < N ; ++i){
can[i][] = ;
for(int j = ; j < ( << N) ; ++j)
if(!(j & ( << i)))
if(can[i][j - (j & -j)]){
int minN = logg2[j & -j];
if(!edge[i][minN])
can[i][j] = ;
}
}
for(int i = ; i < ( << N) ; ++i)
if(cnt1[i] == maxN)
dp[N][i] = ;
for(int i = N - ; i ; --i)
for(int j = ; j < ( << N) ; ++j)
if(cnt1[j] <= i && cnt1[j] <= maxN){
int cnt = ;
for(int p = (( << N) - ) ^ j ; p ; p ^= p & -p){
int k = logg2[p & -p];
if(can[k][j])
dp[i][j] = (dp[i][j] + dp[i + ][j | ( << k)]) % MOD;
else
++cnt;
}
dp[i][j] = (dp[i][j] + 1ll * dp[i + ][j] * (cnt + cnt1[j] - i)) % MOD;
}
long long sum = , ans = ;
for(int i = ; i < N ; ++i)
sum = (sum + dp[][ << i]) % MOD;
for(int i = ; i <= N ; ++i)
ans = ans * i % MOD;
cout << sum * poww(ans , MOD - ) % MOD;
return ;
}

②$f_{j}$表示当前已经无法选择(即已经选择和与已经选择的点相邻的点)的集合为$j$时、独立集取到最大的方案数,设$w_i$表示与$i$相邻(包括$i$)的点集,则有转移:$f_{S \cup w_i}+=f_{S} \times P_{N - |S| - 1}^{|S| - |S \cap w_i| - 1}$,记得要满足最大独立集大小要是最大的。

复杂度$O(2^nn)$

 #include<bits/stdc++.h>
//This code is written by Itst
using namespace std; inline int read(){
int a = ;
bool f = ;
char c = getchar();
while(c != EOF && !isdigit(c)){
if(c == '-')
f = ;
c = getchar();
}
while(c != EOF && isdigit(c)){
a = (a << ) + (a << ) + (c ^ '');
c = getchar();
}
return f ? -a : a;
} const int MOD = ;
long long dp[ << ] , maxN[ << ] , cnt1[ << ] , need[] , jc[] = {} , ny[] = {} , N , M; inline int poww(long long a , int b){
int times = ;
while(b){
if(b & )
times = times * a % MOD;
a = a * a % MOD;
b >>= ;
}
return times;
} int main(){
#ifndef ONLINE_JUDGE
freopen("2540.in" , "r" , stdin);
//freopen("2540.out" , "w" , stdout);
#endif
N = read();
for(int i = ; i < << N ; ++i)
cnt1[i] = cnt1[i - (i & -i)] + ;
jc[] = ny[] = ;
for(int i = ; i <= N ; ++i)
jc[i] = jc[i - ] * i % MOD;
ny[N] = poww(jc[N] , MOD - );
for(int i = N - ; i > ; --i)
ny[i] = ny[i + ] * (i + ) % MOD;
for(int i = ; i < N ; ++i)
need[i] = << i;
for(M = read() ; M ; --M){
int a = read() - , b = read() - ;
need[a] |= << b;
need[b] |= << a;
}
dp[] = ;
for(int i = ; i + < ( << N) ; ++i)
for(int j = ; j < N ; ++j)
if(!(i & ( << j)) && maxN[i] + >= maxN[i | need[j]]){
if(maxN[i] + > maxN[i | need[j]]){
maxN[i | need[j]] = maxN[i] + ;
dp[i | need[j]] = ;
}
dp[i | need[j]] = (dp[i | need[j]] + dp[i] * jc[N - cnt1[i] - ] % MOD * ny[N - cnt1[i] - - (cnt1[need[j]] - cnt1[i & need[j]] - )]) % MOD;
}
cout << dp[( << N) - ] * ny[N] % MOD;
return ;
}

LOJ2540 PKUWC2018 随机算法 状压DP的更多相关文章

  1. [LOJ2540] [PKUWC2018] 随机算法

    题目链接 LOJ:https://loj.ac/problem/2540 Solution 写的时候脑子不太清醒码了好长然后时间\(LOJ\)垫底... 反正随便状压\(dp\)一下就好了,设\(f[ ...

  2. LOJ2540 [PKUWC2018] 随机算法 【状压DP】

    题目分析: 听说这题考场上能被$ O(4^n) $的暴力水过,难不成出题人是毕姥爷? 首先思考一个显而易见的$ O(n^2*2^n) $的暴力DP.一般的DP都是考虑最近的加入了哪个点,然后删除后递归 ...

  3. 洛谷 P4547 & bzoj 5006 随机二分图 —— 状压DP+期望

    题目:https://www.luogu.org/problemnew/show/P4547 https://www.lydsy.com/JudgeOnline/problem.php?id=5006 ...

  4. loj2540 「PKUWC2018」随机算法 【状压dp】

    题目链接 loj2540 题解 有一个朴素三进制状压\(dp\),考虑当前点三种状态:没考虑过,被选入集合,被排除 就有了\(O(n3^{n})\)的转移 但这样不优,我们考虑优化状态 设\(f[i] ...

  5. 【洛谷5492】[PKUWC2018] 随机算法(状压DP)

    点此看题面 大致题意: 用随机算法求一张图的最大独立集:每次随机一个排列,从前到后枚举排列中的点,如果当前点加入点集中依然是独立集,就将当前点加入点集中,最终得到的点集就是最大独立集.求这个随机算法的 ...

  6. 「算法笔记」状压 DP

    一.关于状压 dp 为了规避不确定性,我们将需要枚举的东西放入状态.当不确定性太多的时候,我们就需要将它们压进较少的维数内. 常见的状态: 天生二进制(开关.选与不选.是否出现--) 爆搜出状态,给它 ...

  7. 算法笔记-状压dp

    状压dp 就是把状态压缩的dp 这样还是一种暴力但相对于纯暴力还是优雅的多. 实际上dp就是经过优化的暴力罢了 首先要了解位运算 给个链接吧 [https://blog.csdn.net/u01337 ...

  8. Luogu4547 THUWC2017 随机二分图 概率、状压DP

    传送门 考虑如果只有$0$组边要怎么做.因为$N \leq 15$,考虑状压$DP$.设$f_i$表示当前的匹配情况为$i$时的概率($i$中$2^0$到$2^{N-1}$表示左半边的匹配情况,$2^ ...

  9. 算法复习——状压dp

    状压dp的核心在于,当我们不能通过表现单一的对象的状态来达到dp的最优子结构和无后效性原则时,我们可能保存多个元素的有关信息··这时候利用2进制的01来表示每个元素相关状态并将其压缩成2进制数就可以达 ...

随机推荐

  1. IDEA错误:Failed to start end point associated with ProtocolHandler [http-nio-9999] java.net.BindException: Address already in use: bind

    日志显示进程端口已被占用,首先需要的是查询什么进程占用了当前的9999端口. 1.win+R输入cmd进入命令界面: 2.输入命令  netstat -ano|findstr "端口号&qu ...

  2. memcached分析

    memcache介绍 memcache是一个高性能的分布式的内存对象缓存系统,用于动态Web应用以减轻数据库负担.它通过在内存中缓存数据和对象,来减少读取数据库的次数.从而提高动态.数据库驱动网站速度 ...

  3. (网页)理解Angular中的$apply()以及$digest()

    转自CSDN: 工作有问题上CSDN上转转. $apply()和$digest()在AngularJS中是两个核心概念,但是有时候它们又让人困惑.而为了了解AngularJS的工作方式,首先需要了解$ ...

  4. JavaScript大杂烩14 - 使用JQuery(上)

    JQuery意义 - Why? 为什么要使用JQuery,从我个人来说,就是这么几点:简化代码 + 统一行为 + 功能强大 + 搭配方便. 简化代码是从写代码的角度来说的,实现同样的功能,如果用Jav ...

  5. VMware虚拟机安装教程详解图文

            学习Linux系统最好的方式就是在自己的虚拟机上安装Linux:接下来就给大家简单介绍一下VMware虚拟机的安装以及Linux的安装:VMware虚拟机只是为了更好的学习Linux: ...

  6. 02-OpenLDAP配置

    OpenLDAP配置 在OpenLDAP 2.4版本中,配置OpenLDAP的方法有两种:一种通过修改配置文件实现配置,另一种通过修改数据库的形式完成配置. 通过配置数据库完成各种配置,属于动态配置且 ...

  7. C#语言————第二章 C#语言快速热身

    第二章    C#语言快速热身 ***********一.选择结构**************** 1:if选择结构与java的if选择结构语法完全相同 2:switch选择结构 ①:常量表达式的值可 ...

  8. 第七章 鼠标(CONNECT)

    /* CONNECT.C -- Connect-the-Dots Mouse Demo Program (c) Charles Petzold,1998 */ #include <Windows ...

  9. 字符串通过在配置文件配置三个key来进行加密解密

    在这里和大家分享一个加密util,相对于md5加密相信大家都已经很熟悉了吧,md5是不可逆的一种加密方式,虽说不可逆但是网上已经有了破解的方法,我这边分享一个免费的破解 网址给大家:https://w ...

  10. Logstash收集nginx访问日志和错误日志

    1.收集访问日志 1).首先是要在nginx里面配置日志格式化输出 log_format main "$http_x_forwarded_for | $time_local | $reque ...