传送门


两种$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. 谈谈web上各种图片应用的优缺点

    web中承载信息的主要方式就是图片与文字了,以下就是对一些web图片格式的优缺点进行归纳. 1.GIF GIF图是比较古老的web图片格式之一,可以追溯到1987,几乎所有的浏览器都支持这一种格式,老 ...

  2. QGIS中坐标偏移处理

    to_real("LGTD")+(randf(0.0,1.0)-0.5)*2/1000000.0 getRandomValue() import numpy def getRand ...

  3. Lightning框架示例 - 动态建立Lightning组件

    动态建立Lightning组件 组件化前端开发是Lightning框架的优点之一.在进行Lightning应用开发时,我们可以将组件进行嵌套.引用,从而实现模块的封装和重用,提高开发效率. 组件的嵌套 ...

  4. Oracle win32_11gR2_database在Win7下的安装与卸载

    Oracle win32_11gR2_database在Win7下的安装与卸载 by:授客 QQ:1033553122 Oracle的硬件要求 在安装oracle之前,请检查一下自己的电脑硬件是否复合 ...

  5. recovery 恢复出厂设置失败Data wipe failed

    最近客户反馈,编译32位的android系统,在recovery中执行恢复出厂设置的时候失败了,失败的打印提升信息如下. Formatting /data... [ 2.191404] E:get_f ...

  6. mysql 的一些事

    给mysql的root用户设置密码 1.刚安装好的mysql是没有设置密码的 2.设置密码 ****************************************************** ...

  7. scp 实现远程异地备份

    1.先做好脚本 2.再使用crontab 定时执行计划任务 0 1 * * * /usr/bin/expect /root/script/scpautodown.sh  #执行,也可先定义环境变量 0 ...

  8. Dota 2 中安装包的作用

    在玩data 2 的时候有很多其他安装包的下载,那这些有啥用呢? Reborn是Dota2的重生客户端,也就是主客户端. Opengl是显卡优化的,应该是微软的一个标准,有助于提高游戏的 FPS. V ...

  9. Emmet快速编写代码

    Emmet快速编写代码 ★div → <div></div>, span → <span></span> ★CSS选择器 ​ 给标签指定id选择器 di ...

  10. 【PAT】B1060 爱丁顿数(25 分)

    逻辑问题,对我来说还是挺有难度的,一开始想不通 我输入数据并以数据为下标,数据出现次数为内容存储 然后从后遍历计算所有大于当前下标的元素出现的次数 最后遍历一遍确定是否为爱丁顿数,如果大于当前已经找到 ...