传送门


两种$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. javascript选项卡切换样式

    HTML代码 <ul class="touzi_xuan1" id="qixian"> <li>****: </li> &l ...

  2. js 键盘码

    键盘各按键对应的数字 keycode 9 = Tab keycode 12 = Clear keycode 13 = Enter keycode 16 = Shift keycode 17 = Con ...

  3. Linux 操作系统下的环境变量设置

    Linux下的环境变量设置 by:授客 QQ:1033553122 1.  问题描述 linux输入命令时经常会出现提示:xxx:Command not found 2.  原因分析 Command ...

  4. CSS模糊效果及其兼容方法

    今天在整理IE滤镜时网站访问这里,居然找到模糊滤镜blur(),感觉太不可思议了,想不到IE居然会有这么多种滤镜效果,这基本上是模仿PS的.今天的重点是模糊滤镜 CSS模糊效果及其兼容方法 实例 兼容 ...

  5. 使用wxpy自动发送微信消息(加强版)

    通过使用wxpy自动发送微信消息后,笔者又加强了发送消息,堪称消息爆炸式发送 目前设置的为10秒发送一次,发送9次,每次发送10条内容 import requests import wxpy from ...

  6. Python和Lua的默认作用域以及闭包

    默认作用域 前段时间学了下Lua,发现Lua的默认作用域和Python是相反的.Lua定义变量时默认变量的作用域是全局(global,这样说不是很准确,Lua在执行x = 1这样的语句时会从当前环境开 ...

  7. rbac models

    class Permission(models.Model): """ 权限表 """ perm_name = models.CharFie ...

  8. 解决eclipse启动慢

    每次启动eclipse时都要等待半分钟左右,对于追求效率的程序员来说,等待每一秒都是一种折磨,出于高效开发的精神,这个问题必须解决掉.方案如下: ①在工具栏中的help中找到about eclipse ...

  9. BeanFactory中Bean的生命周期

    Bean的生命周期图解 集体过程如下: 当调用者通过getBean(beanName)向容器请求某一个Bean时,如果容器注册了org.springframework.beans.factory.co ...

  10. JdbcTemolate类的介绍<一>

    JdbcTemolate类的介绍 JdbcTemplate是Spring JDBC的核心类,封装了常见的JDBC的用法,同时尽量避免常见的错误.该类简化JDBC的操作,我们只需要书写提供SQL的代码和 ...