【LOJ】#2290. 「THUWC 2017」随机二分图
题解
看了一眼觉得是求出图对图统计完美匹配的个数(可能之前做过这样模拟题弃疗了,一直心怀恐惧。。。
然后说是统计一下每种匹配出现的概率,也就是,当前左边点匹配状态为S,右边点匹配状态为T,每种匹配出现的概率的总和作为\(f[S][T]\),我们需要的就是\(f[2^{n} - 1][2^{n} - 1]\)
然而,会发现转移起来似乎非常麻烦,例如,假如两条边一起出现,各自匹配出现的概率是多少?
我们把每组边拆开,变成每条边在匹配中有50%概率出现,一组边同时在匹配中出现的概率是25%,如果t = 2,那么概率就是-25%
为什么呢,对于t = 1的边,两条肯定一起出现,那么如果我们算第一条边进入匹配,概率是50%,算第二条边进入匹配,概率也是50%,但是由于两条边一起出现的特殊性质,我们按照这个方法算,如果两个匹配都出现的概率是25%,但是两条匹配都出现的概率是50%,我们就加上一个25%两条边一起匹配
同理,对于t = 2的边,第一条边进去匹配是50%,第二条边进入匹配是50%,然而两条边一起进入匹配是不可能的,只有减掉那25%的概率了
代码
#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <map>
//#define ivorysi
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define mp make_pair
#define pb push_back
#define fi first
#define se second
#define mo 974711
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
res = 0;char c = getchar();T f = 1;
while(c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9') {
res = res * 10 + c - '0';
c = getchar();
}
res *= f;
}
template<class T>
void out(T x) {
if(x < 0) {putchar('-');x = -x;}
if(x >= 10) {
out(x / 10);
}
putchar('0' + x % 10);
}
const int MOD = 1000000007;
int N,M,tot,fir[(1 << 15) + 1];
struct Edge{
int a[2],b[2],val;
}E[10005];
vector<int> MK[20];
map<int,int> f[(1 << 15) + 5];
int fpow(int x,int c) {
int res = 1,t = x;
while(c) {
if(c & 1) res = 1LL * res * t % MOD;
t = 1LL * t * t % MOD;
c >>= 1;
}
return res;
}
void Init() {
read(N);read(M);
int t,a0,a1,b0,b1;
int Inv2 = (MOD + 1) / 2,Inv4 = 1LL * Inv2 * Inv2 % MOD;
for(int i = 1 ; i <= M ; ++i) {
read(t);read(a0);read(b0);
if(t == 0) {
E[++tot].a[0] = a0;E[tot].b[0] = b0;E[tot].val = Inv2;
MK[a0].pb(tot);
}
else {
read(a1);read(b1);
E[++tot].a[0] = a0;E[tot].b[0] = b0;E[tot].val = Inv2;MK[a0].pb(tot);
E[++tot].a[0] = a1;E[tot].b[0] = b1;E[tot].val = Inv2;MK[a1].pb(tot);
E[++tot].a[0] = a0;E[tot].b[0] = b0;E[tot].a[1] = a1;E[tot].b[1] = b1;E[tot].val = Inv4;
MK[a0].pb(tot);MK[a1].pb(tot);
if(t == 2) E[tot].val = MOD - Inv4;
}
}
}
void update(int &x,int y) {
x += y;
while(x >= MOD) x -= MOD;
}
void Solve() {
fir[0] = 1;
for(int i = 1 ; i < (1 << N) ; ++i) {
fir[i] = min(fir[i >> 1] + 1,(i & 1) ? N + 1 : 1);
}
f[0][0] = 1;
for(int S = 0 ; S < (1 << N) ; ++S) {
for(auto k : f[S]) {
int T = k.fi,val = k.se;
//printf("%d %d %d\n",S,T,val);
for(auto id : MK[fir[S]]) {
if(T >> (E[id].b[0] - 1) & 1) continue;
if(S >> (E[id].a[0] - 1) & 1) continue;
if(E[id].a[1]) {
if(E[id].a[0] == E[id].a[1] || E[id].b[0] == E[id].b[1]) continue;
if(T >> (E[id].b[1] - 1) & 1) continue;
if(S >> (E[id].a[1] - 1) & 1) continue;
int a0 = E[id].a[0] - 1,a1 = E[id].a[1] - 1;
int b0 = E[id].b[0] - 1,b1 = E[id].b[1] - 1;
update(f[S | (1 << a0) | (1 << a1)][T | (1 << b0) | (1 << b1)],1LL * val * E[id].val % MOD);
}
else {
int a0 = E[id].a[0] - 1,b0 = E[id].b[0] - 1;
update(f[S | (1 << a0)][T | (1 << b0)],1LL * val * E[id].val % MOD);
}
}
}
}
int ans = 1LL * fpow(2,N) * f[(1 << N) - 1][(1 << N) - 1] % MOD;
out(ans);enter;
}
int main() {
#ifdef ivorysi
freopen("f1.in","r",stdin);
#endif
Init();
Solve();
return 0;
}
【LOJ】#2290. 「THUWC 2017」随机二分图的更多相关文章
- @loj - 2290@ 「THUWC 2017」随机二分图
目录 @description@ @solution@ @accepted code@ @details@ @description@ 一个左右各 n 个点的二分图,图中的边会按照一定的规律随机出现. ...
- 「THUWC 2017」随机二分图
「THUWC 2017」随机二分图 解题思路 : 首先有一个 \(40pts\) 的做法: 前 \(20pts\) 暴力枚举最终的匹配是怎样的,check一下计算方案数,后 \(20pts\) 令 \ ...
- LOJ 2288「THUWC 2017」大葱的神力
LOJ 2288「THUWC 2017」大葱的神力 Link Solution 比较水的提交答案题了吧 第一个点爆搜 第二个点爆搜+剪枝,我的剪枝就是先算出 \(mx[i]\) 表示选取第 \(i \ ...
- @loj - 2289@「THUWC 2017」在美妙的数学王国中畅游
目录 @description@ @solution@ @accepted code@ @details@ @description@ n 个点编号 0 到 n-1,每个点有一个从 [0,1] 映射到 ...
- @loj - 2288@「THUWC 2017」大葱的神力
目录 @description@ @solution@ @data - 1@ @data - 2@ @data - 3@ @data - 4@ @data - 5@ @data - 6@ @data ...
- LOJ #2540. 「PKUWC 2018」随机算法(概率dp)
题意 LOJ #2540. 「PKUWC 2018」随机算法 题解 朴素的就是 \(O(n3^n)\) dp 写了一下有 \(50pts\) ... 大概就是每个点有三个状态 , 考虑了但不在独立集中 ...
- LOJ #2542. 「PKUWC 2018」随机游走(最值反演 + 树上期望dp + FMT)
写在这道题前面 : 网上的一些题解都不讲那个系数是怎么推得真的不良心 TAT (不是每个人都有那么厉害啊 , 我好菜啊) 而且 LOJ 过的代码千篇一律 ... 那个系数根本看不出来是什么啊 TAT ...
- 「LOJ 2289」「THUWC 2017」在美妙的数学王国中畅游——LCT&泰勒展开
题目大意: 传送门 给一个动态树,每个节点上维护一个函数为$f(x)=sin(ax+b)$.$f(x)=e^{ax+b}$.$f(x)=ax+b$中的一个. 支持删边连边,修改节点上函数的操作. 每次 ...
- 【LOJ】#2289. 「THUWC 2017」在美妙的数学王国中畅游
题解 我们发现,题目告诉我们这个东西就是一个lct 首先,如果只有3,问题就非常简单了,我们算出所有a的总和,所有b的总和就好了 要是1和2也是多项式就好了--其实可以!也就是下面泰勒展开的用处,我们 ...
随机推荐
- weUI框架在github下载地址
1.公众号样式UI库的下载地址: https://github.com/Tencent/weui 2.微信小程序UI库的下载地址:https://github.com/Tencent/weui-wxs ...
- Vue.js学习笔记(一)
其它前端主流框架可以做的事,Vue.js几乎都可以做, nuxt框架:可以实现vue的服务器端渲染, weex:使用vue语法编写原生app. 基础内容 基础语法 MVVM设计模式 前端组件化 vue ...
- [转载]代码编辑器Sublime Text 3 免费使用方法与简体中文汉化包下载
http://devework.com/sublime-text-3.html Sublime Text这款代码编辑器是Jeff 一直都在使用的,前段时间转用到版本3,因为感觉Sublime Text ...
- jquery中美元符号命名冲突问题解决
在Jquery中,$是JQuery的别名,所有使用$的地方也都可以使用JQuery来替换,如$('#msg')等同于JQuery('#msg') 的写法.然而,当我们引入多个js库后,在另外一个js库 ...
- 线搜索(line search)方法
在机器学习中, 通常需要求某个函数的最值(比如最大似然中需要求的似然的最大值). 线搜索(line search)是求得一个函数\(f(x)\)的最值的两种常用迭代方法之一(另外一个是trust re ...
- kafka入门(2)- 环境部署
部署Zookeeper(单机/集群) 1.下载安装文件: http://mirror.bit.edu.cn/apache/zookeeper/ 2.解压文件(本文解压到 D:\zookeeper-3. ...
- Concat层解析
Concat层的作用就是将两个及以上的特征图按照在channel或num维度上进行拼接,并没有eltwise层的运算操作,举个例子,如果说是在channel维度上进行拼接conv_9和deconv_9 ...
- HDU 1010 Tempter of the Bone (广搜+减枝)
题目链接 Problem Description The doggie found a bone in an ancient maze, which fascinated him a lot. How ...
- 添加 MySql 服务、Tomcat服务到windows服务中
添加 MySql 服务到windows服务中: cmd --> F:\MySql\MySqlServer5.1\bin\mysqld --install 这样用默认的 MySQL 为名称添加一个 ...
- Understanding the Space Used by ZFS -- (转)
Understanding the Space Used by ZFS By Brian Leonard on Sep 28, 2010 Until recently, I've been confu ...