Luogu4547 THUWC2017 随机二分图 概率、状压DP
考虑如果只有$0$组边要怎么做。因为$N \leq 15$,考虑状压$DP$。设$f_i$表示当前的匹配情况为$i$时的概率($i$中$2^0$到$2^{N-1}$表示左半边的匹配情况,$2^N$到$2^{2N-1}$表示右半边的匹配情况),转移就是随便取一条边将其起终边对应的位置去掉然后乘上$0.5$。
然而会发现这会重复转移,也就是说先选择$a$再选择$b$与先选择$b$再选择$a$在计算中被算作了两种情况,但实际上只能够算作一种。我们考虑固定$DP$的顺序。我们每一次选择$lowbit(i)$对应的点进行转移,这样转移就是左部分的点从小到大连边,转移也就不会重复了。
接着我们考虑$1$组边和$2$组边。首先我们考虑将这两组边中的两条边拆开考虑,这样会有:只选择第一条边参与贡献概率为$50\%$,只选择第二条边参与贡献概率为$50\%$,两条边同时参与贡献概率为$25\%$。发现只有两条边同时参与贡献时的概率是有问题的,所以我们考虑加上一条边。这一条边对应这一组的两条边,对于$1$组边给予其$25\%$的概率,对于$2$组边给予其$-25\%$的概率,这样概率就是对的了。这一条边要在较小的那一个左端点计算的时候进行计算。
上面那个不是很好理解,慢慢思考一下qwq
最后,$2^{30}$的数组是不可能开下的,考虑到有很多冗余状态,使用记忆化搜索就可以通过这道题了。
#include<bits/stdc++.h>
#define ld long double
//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 MAXN = * ;
const int MOD = 1e9 + ;
struct Edge{
int start , end , belStart , belEnd;
long long p;
}now[MAXN * ];
int range[] , num2[] , poww2[] , N , cnt , inv2 , inv4;
map < int , int > dp; inline void add(int x , int y , int belx , int bely , int p){
now[++cnt].start = x;
now[cnt].end = y;
now[cnt].belStart = belx;
now[cnt].belEnd = bely;
now[cnt].p = p;
} bool operator <(Edge a , Edge b){
return a.start < b.start;
} int dfs(int dir){
if(dp.count(dir))
return dp[dir];
if(!dir)
return ;
int t = num2[dir & -dir] , sum = ;
for(int i = range[t] ; i < range[t + ] ; ++i)
if(dir & poww2[now[i].end])
if(now[i].belStart == -)
sum = (sum + dfs(dir ^ poww2[t] ^ poww2[now[i].end]) * now[i].p) % MOD;
else
if((dir & poww2[now[i].belStart]) && (dir & poww2[now[i].belEnd]))
sum = (sum + dfs(dir ^ poww2[t] ^ poww2[now[i].end] ^ poww2[now[i].belStart] ^ poww2[now[i].belEnd]) * now[i].p) % MOD;
return dp[dir] = sum;
} 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("4547.in" , "r" , stdin);
//freopen("4547.out" , "w" , stdout);
#endif
N = read();
for(int i = ; i < N ; ++i)
num2[ << i] = i;
poww2[] = ;
for(int i = ; i < (N << ) ; ++i)
poww2[i] = poww2[i - ] << ;
inv2 = poww( , MOD - );
inv4 = poww( , MOD - );
for(int M = read() ; M ; --M){
int t = read() , x = read() - , y = read() + N - ;
add(x , y , - , - , inv2);
if(t){
int belx = read() - , bely = read() + N - ;
add(belx , bely , - , - , inv2);
if(belx < x){
swap(x , belx);
swap(y , bely);
}
if(belx != x && bely != y)
add(x , y , belx , bely , t == ? inv4 : MOD - inv4);
}
}
sort(now + , now + cnt + );
for(int i = ; i <= cnt ; ++i)
if(!range[now[i].start])
range[now[i].start] = i;
range[N] = cnt + ;
printf("%lld\n" , 1ll * dfs(( << (N << )) - ) * poww( , N) % MOD);
return ;
}
Luogu4547 THUWC2017 随机二分图 概率、状压DP的更多相关文章
- [BZOJ5006][LOJ#2290][THUWC2017]随机二分图(概率+状压DP)
https://loj.ac/problem/2290 题解:https://blog.csdn.net/Vectorxj/article/details/78905660 不是很好理解,对于边(x1 ...
- [思路题][LOJ2290][THUWC2017]随机二分图:状压DP+期望DP
分析 考虑状压DP,令\(f[sta]\)表示已匹配状态是\(sta\)(\(0\)代表已匹配)时完美匹配的期望数量,显然\(f[0]=1\). 一条边出现了不代表它一定在完美匹配内,这也导致很难去直 ...
- P4547 [THUWC2017]随机二分图(状压,期望DP)
期望好题. 发现 \(n\) 非常小,应该要想到状压的. 我们可以先只考虑 0 操作. 最难的还是状态: 我们用 \(S\) 表示左部点有哪些点已经有对应点, \(T\) 表示右部点有哪些点已经有对应 ...
- 【洛谷5492】[PKUWC2018] 随机算法(状压DP)
点此看题面 大致题意: 用随机算法求一张图的最大独立集:每次随机一个排列,从前到后枚举排列中的点,如果当前点加入点集中依然是独立集,就将当前点加入点集中,最终得到的点集就是最大独立集.求这个随机算法的 ...
- Codeforces Round #363 LRU(概率 状压DP)
状压DP: 先不考虑数量k, dp[i]表示状态为i的概率,状态转移方程为dp[i | (1 << j)] += dp[i],最后考虑k, 状态表示中1的数量为k的表示可行解. #incl ...
- NOIP2016提高A组 A题 礼物—概率状压dp
题目描述 夏川的生日就要到了.作为夏川形式上的男朋友,季堂打算给夏川买一些生 日礼物. 商店里一共有n种礼物.夏川每得到一种礼物,就会获得相应喜悦值Wi(每种礼物的喜悦值不能重复获得). 每次,店员会 ...
- loj2540 「PKUWC2018」随机算法 【状压dp】
题目链接 loj2540 题解 有一个朴素三进制状压\(dp\),考虑当前点三种状态:没考虑过,被选入集合,被排除 就有了\(O(n3^{n})\)的转移 但这样不优,我们考虑优化状态 设\(f[i] ...
- LOJ2540 [PKUWC2018] 随机算法 【状压DP】
题目分析: 听说这题考场上能被$ O(4^n) $的暴力水过,难不成出题人是毕姥爷? 首先思考一个显而易见的$ O(n^2*2^n) $的暴力DP.一般的DP都是考虑最近的加入了哪个点,然后删除后递归 ...
- POJ2794 Double Patience[离散概率 状压DP]
Double Patience Time Limit: 3000MS Memory Limit: 65536K Total Submissions: 694 Accepted: 368 Cas ...
随机推荐
- cors解决跨域问题
在作前后端分离的时候,我们总是要做跨域处理. 使用 express 框架搭建项目的时候可以设置如下: app.use(function (req, res, next) { res.setHeader ...
- 关于Bootstrap fileinput 上传新文件,移除时触发服务器同步删除的配置
在Bootstrap fileinput中移除预览文件时可以通过配置initialPreviewConfig: [ { url:'deletefile',key:fileid } ] 来同步删除服务器 ...
- 反编译Apk得到Java源代码
原文章转载自:http://hi.baidu.com/%CB%BF%D4%B5%CC%EC%CF%C2/blog/item/2284e2debafc541e495403ec.html 本人转载自:ht ...
- C++ UTF8 UrlEncode(宽字符)
为了支持C++ UrlEncode之后的字符串能够被C#所识别(windows phone 下C#只能支持UTF8与 Unicode). 所谓的 UTF8 UrlEncode 也只是宽字符串 UrlE ...
- (网页)JS实现alert中显示换行的方法
转自脚本之家: 这篇文章主要介绍了JS实现alert中显示换行的方法,实例分析了两种实现alert换行的实现技巧,非常简单实用,需要的朋友可以参考下 本文实例讲述了JS实现alert中显示换行的方法. ...
- 利用搜狐新闻语料库训练100维的word2vec——使用python中的gensim模块
关于word2vec的原理知识参考文章https://www.cnblogs.com/Micang/p/10235783.html 语料数据来自搜狐新闻2012年6月—7月期间国内,国际,体育,社会, ...
- Scala多重继承及AOP
package traitandclass /** * Created by zhen on 2018/8/23. */ class Human { println("Human" ...
- maven五:查找jar包坐标,选择jar包版本
查找jar包坐标 以spring core的jar包为例,访问http://www.mvnrepository.com/ 在最上方中间,输入spring core,点击Search. 搜索结果第 ...
- VB6 对象库未注册问题
以下是个人使用VB6出现对象库未注册问题的解决方法.已成功! 一.注册ocx文件 mscomctl.ocx文件放进路径C:\Windows\System32(64是此路径,由于本人是64位系统32位未 ...
- zabbix监控磁盘IO
我这里有两种方法,感觉都不错.我这里主要是写一下监控的脚本. 1.使用iostat命令监控 1)首先打开配置文件的自定义脚本功能,然后编写脚本. #!/bin/bash ];then echo &qu ...