传送门


考虑如果只有$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的更多相关文章

  1. [BZOJ5006][LOJ#2290][THUWC2017]随机二分图(概率+状压DP)

    https://loj.ac/problem/2290 题解:https://blog.csdn.net/Vectorxj/article/details/78905660 不是很好理解,对于边(x1 ...

  2. [思路题][LOJ2290][THUWC2017]随机二分图:状压DP+期望DP

    分析 考虑状压DP,令\(f[sta]\)表示已匹配状态是\(sta\)(\(0\)代表已匹配)时完美匹配的期望数量,显然\(f[0]=1\). 一条边出现了不代表它一定在完美匹配内,这也导致很难去直 ...

  3. P4547 [THUWC2017]随机二分图(状压,期望DP)

    期望好题. 发现 \(n\) 非常小,应该要想到状压的. 我们可以先只考虑 0 操作. 最难的还是状态: 我们用 \(S\) 表示左部点有哪些点已经有对应点, \(T\) 表示右部点有哪些点已经有对应 ...

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

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

  5. Codeforces Round #363 LRU(概率 状压DP)

    状压DP: 先不考虑数量k, dp[i]表示状态为i的概率,状态转移方程为dp[i | (1 << j)] += dp[i],最后考虑k, 状态表示中1的数量为k的表示可行解. #incl ...

  6. NOIP2016提高A组 A题 礼物—概率状压dp

    题目描述 夏川的生日就要到了.作为夏川形式上的男朋友,季堂打算给夏川买一些生 日礼物. 商店里一共有n种礼物.夏川每得到一种礼物,就会获得相应喜悦值Wi(每种礼物的喜悦值不能重复获得). 每次,店员会 ...

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

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

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

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

  9. POJ2794 Double Patience[离散概率 状压DP]

    Double Patience Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 694   Accepted: 368 Cas ...

随机推荐

  1. 二层协议--LLDP协议总结

    二层协议--LLDP协议总结,待完善.

  2. loadrunner 场景设计-目标场景设计

    场景设计-目标场景设计 by:授客 QQ:1033553122 A.   概述 Goals Types for Goal-Oriented Scenarios 在以目标为向导的场景中,定义你想实现的测 ...

  3. JavaScript 字符串转json格式

    第一种:浏览器支持的转换方式(Firefox,chrome,opera,safari,ie)等浏览器: JSON.parse(jsonstr); //可以将json字符串转换成json对象 JSON. ...

  4. 安装VisualSVN Server 报"Service 'VisualSVN Server' failed to start. Please check VisualSVN Server log in Event Viewer for more details"错误.原因是启动"VisualSVN Server"失败

    安装VisualSVN Server 报"Service 'VisualSVN Server' failed to start. Please check VisualSVN Server ...

  5. 3.1Python数据处理篇之Numpy系列(一)---ndarray对象的属性与numpy的数据类型

    目录 目录 (一)简单的数组创建 1.numpy的介绍: 2.numpy的数组对象ndarray: 3.np.array(list/tuple)创建数组: (二)ndarray对象的属性 1.五个常用 ...

  6. Java设计模式之七 ----- 享元模式和代理模式

    前言 在上一篇中我们学习了结构型模式的组合模式和过滤器模式.本篇则来学习下结构型模式最后的两个模式, 享元模式和代理模式. 享元模式 简介 享元模式主要用于减少创建对象的数量,以减少内存占用和提高性能 ...

  7. Mac OS X 下优化 Terminal,一篇就够了!

    先上最终效果图: 目录 目录 1. 相关工具介绍 2. 配置总览 3. 安装步骤 3.1. 安装 iTerm2 3.2. 安装XCode's Command line tools 3.3. 检查 zs ...

  8. 2019年京东Java研发岗社招面经(面试经历+真题总结+经验分享)!

    本篇先以日历形式回顾秋招之路,方便各位参考某厂的处理进度:然后是总结归纳春秋招Java面试题库:最后做个总结还有展望,开始新的征程~ 面试经历京东面试真题面试经验分享1.面试经历 2018年的冬季特别 ...

  9. 控件_ImageView

    ImageView(图片视图)的基本概念:就是将一张图片放在一个Activity中显示出来,就是一个放图片的容器 import android.app.Activity; import android ...

  10. SHELL-收集Oracle已应用的PSU信息

    1. 命令收集版本信息 # 创建数据收集脚本文件 OPER_FILE=${EXECUTE_ID}_oper.sh if [[ "${OPER_USER}" = "${US ...