【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也是多项式就好了--其实可以!也就是下面泰勒展开的用处,我们 ...
随机推荐
- 科学计算三维可视化---Mayavi入门(Mayavi库的基本元素和绘图实例)
一:Mayavi库的基本元素 .处理图形可视化和图形操作的mlab模块 .操作管线对象,窗口对象的api (一)mlab模块 (二)mayavi的api 二:快速绘图实例 (一)mlab.mesh的使 ...
- Linux入门,这七大习惯得有!
对于很多Linux初学者来说,在刚开始使用Linux系统时会感到很多不适.这里为大家整理了自己以前Linux入门时别人告诉我的七个习惯.我相信如果你运用了这七个习惯,在你使用Linux时你会感觉更安全 ...
- Mongodb 笔记03 查询、索引
查询 1. MongoDB使用find来进行查询.find的第一个参数决定了要返回哪些文档,这个参数是一个文档,用于指定查询条件.空的查询会匹配集合的全部内容.要是不指定查询,默认是{}. 2. 可以 ...
- 深入浅出CSS(三):隐藏BOSS大盘点之默认属性小总结
写在前面 严重警告,本文包含大量文字,且无配图,请做好充分心理准备后,再进行阅读! 严重警告,本文包含大量文字,且无配图,请做好充分心理准备后,再进行阅读! 严重警告,本文包含大量文字,且无配图,请做 ...
- C++的一些不错开源框架,可以学习和借鉴
from https://www.cnblogs.com/charlesblc/p/5703557.html [本文系外部转贴,原文地址:http://coolshell.info/c/c++/201 ...
- 服务器能ping通ip,通不了域名解决方案
# 将网卡配置文件配置固定ip后,添加DNS解析,然后重启网卡即可: [root@a ~]# tail -2 /etc/sysconfig/network-scripts/ifcfg-ens160 D ...
- Django 2.0.1 官方文档翻译: 如何安装 django (Page 17)
如何安装 django(Page 17) 这一部分可以让你将 Django 运行起来. 安装 Python 作为 python 的一个 web 框架,Django 依赖 Python.Python 的 ...
- Java并发编程原理与实战二十七:循环栅栏:CyclicBarrier
昨天我们学习了倒计数功能的等待,今天我们学习的是循环栅栏:CyclicBarrier.下面我们就开始吧: 1.CyclicBarrier简介CyclicBarrier,是JDK1.5的java.uti ...
- 约翰·卡马克和他的id Software
John Carmack 上帝花了6天创造了这个世界,id software和它的创始人.引擎师约翰·卡马克(John Carmack),则用6款游戏创造了个人电脑的3D世界. 1992年,id做出了 ...
- 渐变色之location概念.
CHENYILONG Blog 渐变色之location概念.全屏幕13-12-22 上午10:18 © chenyilong. Powered by Postach.io Blog