LOJ2540 PKUWC2018 随机算法 状压DP
两种$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的更多相关文章
- [LOJ2540] [PKUWC2018] 随机算法
题目链接 LOJ:https://loj.ac/problem/2540 Solution 写的时候脑子不太清醒码了好长然后时间\(LOJ\)垫底... 反正随便状压\(dp\)一下就好了,设\(f[ ...
- LOJ2540 [PKUWC2018] 随机算法 【状压DP】
题目分析: 听说这题考场上能被$ O(4^n) $的暴力水过,难不成出题人是毕姥爷? 首先思考一个显而易见的$ O(n^2*2^n) $的暴力DP.一般的DP都是考虑最近的加入了哪个点,然后删除后递归 ...
- 洛谷 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进制数就可以达 ...
随机推荐
- 网络基础 Windows控制台下Ftp使用简介
Windows控制台下Ftp使用简介 by:授客 QQ:1033553122 测试环境: ftp服务器所在主机ip:172.25.75.2 ftp用户目录:F:\ftp C:\Users\laif ...
- linux上用newman+postman进行自动化测试
第一步:导出postman文件 Postman就是根据collection和enviroment这两个json文件来自动化运行的! 所以从Postman中导出collection和enviroment ...
- LeetCode题解之Binary Tree Pruning
1.题目描述 2.问题分析 使用递归 3.代码 TreeNode* pruneTree(TreeNode* root) { if (root == NULL) return NULL; prun(ro ...
- charles系列破解激活办法(最高charles4.2都可以激活)
// Charles Proxy License // 适用于Charles任意版本的注册码,谁还会想要使用破解版呢. // Charles 4.2目前是最新版,可用. Registered Na ...
- asp.net mvc中的后台验证
asp.net mvc的验证包含后台验证和前端验证.后台验证主要通过数据注解的形式实现对model中属性的验证,其验证过程发生在model绑定的过程中.前端验证是通过结合jquery.validate ...
- axure元件库导入后重启程序元件库消失问题
把元件库文件放在我的文档里的 \Documents\Axure\元件库 就可以了,重新启动程序不会消失
- 使用Python语言理解递归
递归 一个函数在执行过程中一次或多次调用其本身便是递归,就像是俄罗斯套娃一样,一个娃娃里包含另一个娃娃. 递归其实是程序设计语言学习过程中很快就会接触到的东西,但有关递归的理解可能还会有一些遗漏,下面 ...
- docker端口映射启动报错Error response from daemon: driver failed programming external connectivity on endpoint jms_guacamole
问题描述:今天跳板机的一个guacamole用docker重新启动报错了 [root@localhost opt]# docker start d82e9c342a Error response / ...
- 戴尔dell服务器硬件故障SMTP邮件报警idrac配置
上次公司有台戴尔的服务器硬盘故障了却没有及时发现,后面就研究了一下看到戴尔的idrac有硬件SMTP报警功能 然后自己折腾了一下,一开始配置不成功,后面问了一下戴尔官方的最好自己再摸索了一下解决了,做 ...
- Django框架的使用教程--环境的搭建和项目的创建[一]
Django环境的搭建 Django 常用的命令 # 创建一个名为Django_test子应用 python manage.py startapp Django_test # 生成迁移文件 pytho ...