题目:https://www.lydsy.com/JudgeOnline/problem.php?id=5006

   https://www.luogu.org/problemnew/show/P4547

算一种可行方案,只要确定出 n 条边即可;概率就是这 n 条边存在的概率,其他边视作无要求,概率贡献都是1;这样的话,一种方案对答案的贡献就是其概率。

考虑把第二组边和第三组边分成概率分别为 1/2 的两条独立的边。对于第二组边再加一条能把4个点都连起来的 1/4 的边,对于第三组边再加一条能把4个点都连起来的 -1/4 的边。

因为算一个方案的概率的时候只看选中的边的概率乘积,所以上述方案可以让概率计算正确。

可以设 dp[ s0 ][ s1 ] 表示左部的点集 s0 和右部的点集 s1 匹配的期望方案数。然后记忆化搜索。(也可以刷表,还会快,但不太会写)

为了避免方案数因为加边顺序而算重,可以规定一个顺序,比如转移到 (s0,s1) 的状态 (d0,d1) 的 d0 一定不含 s0 的 lowbit 之类的。

于是枚举 d0 , d1 ,但会TLE。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define mkp make_pair
#define pii pair<int,int>
#define ll long long
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
const int N=,M=,mod=1e9+;
int n,m,bin[N],dy[(<<)+],iv2,iv4; bool s[N][N];
map<pii,int> s2,mp;
int pw(int x,int k)
{int ret=;while(k){if(k&)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=;}return ret;}
void upd(int &x){x>=mod?x-=mod:;}
int dfs(int s0,int s1)
{
pii S=mkp(s0,s1);if(mp.count(S))return mp[S];
int lbt=(s0&-s0);
int x=dy[lbt],y,d0=s0^(lbt),p0=s1,d1;
while(p0)//every bit of s1
{
lbt=(p0&-p0);
y=dy[lbt]; d1=s1^lbt; p0^=lbt;
if(s[x][y])
mp[S]=(mp[S]+(ll)iv2*dfs(d0,d1))%mod;
}
p0=d0; x=(s0&-s0);
while(p0)//every bit of (s0-lowbit)
{
lbt=(p0&-p0); d0=(x|lbt); p0^=lbt;//d0:two bits of s0
int p1=s1;//every bit of s1
while(p1)
{
lbt=(p1&-p1); y=lbt; p1^=lbt;
int p2=p1;//d1:every bit of p1
while(p2)
{
lbt=(p2&-p2); d1=(y|lbt); p2^=lbt;
pii d=mkp(d0,d1);
if(s2.count(d))
mp[S]=(mp[S]+(ll)iv4*dfs(s0^d0,s1^d1)*s2[d])%mod+mod,upd(mp[S]);
}
}
}
return mp[S];
}
int main()
{
int m,t,x1,y1,x2,y2;
n=rdn();m=rdn();
bin[]=;dy[]=;for(int i=;i<=n;i++)bin[i]=bin[i-]<<,dy[bin[i]]=i;
iv2=pw(,mod-); iv4=pw(,mod-); mp[mkp(,)]=bin[n];
for(int i=;i<=m;i++)
{
t=rdn();x1=rdn()-;y1=rdn()-;
if(t)x2=rdn()-,y2=rdn()-;
s[x1][y1]=; if(!t)continue;
s[x2][y2]=;
s2[mkp(bin[x1]|bin[x2],bin[y1]|bin[y2])]=(t==?:-);
}
printf("%d\n",dfs(bin[n]-,bin[n]-));
return ;
}

于是改成枚举每条边,并且把两个点集压进一个数而不是两个数里。但还是TLE。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define mkp make_pair
#define pii pair<int,int>
#define ll long long
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
const int N=,M=,mod=1e9+;
int n,m,bin[N],iv2,iv4;
struct Ed{
int x,y,w;
Ed(int x=,int y=,int w=):x(x),y(y),w(w) {}
}ed[M];
map<pii,int> mp;
int pw(int x,int k)
{int ret=;while(k){if(k&)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=;}return ret;}
void upd(int &x){x>=mod?x-=mod:;}
int dfs(int s0,int s1)
{
pii S=mkp(s0,s1);if(mp.count(S))return mp[S];
int lbt=(s0&-s0);
for(int i=;i<=m;i++)
if((ed[i].x|s0)==s0&&(ed[i].y|s1)==s1&&(ed[i].x&lbt))
mp[S]=(mp[S]+(ll)ed[i].w*dfs(s0^ed[i].x,s1^ed[i].y))%mod;
return mp[S];
}
int main()
{
int tp,t,x1,y1,x2,y2;
n=rdn();tp=rdn();
bin[]=;for(int i=;i<=n;i++)bin[i]=bin[i-]<<;
iv2=pw(,mod-); iv4=pw(,mod-); mp[mkp(,)]=bin[n];
for(int i=;i<=tp;i++)
{
t=rdn();x1=bin[rdn()-];y1=bin[rdn()-];
ed[++m]=Ed(x1,y1,iv2); if(!t)continue;
x2=bin[rdn()-];y2=bin[rdn()-];
ed[++m]=Ed(x2,y2,iv2);
if((x1&x2)||(y1&y2))continue;///
ed[++m]=Ed(x1|x2,y1|y2,t==?iv4:mod-iv4);
}
printf("%d\n",dfs(bin[n]-,bin[n]-));
return ;
}

主要是 map 的大小。在 mp[ s0 ] 里找有没有 s1 比在整个 (s0,s1) 里找有没有 (s0,s1) 快。

并且不要写很多 mp[ s0 ][ s1 ] ,可以用一个临时变量 ret 之类的代替。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<map>
#define ll long long
using namespace std;
int rdn()
{
int ret=;bool fx=;char ch=getchar();
while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
return fx?ret:-ret;
}
const int N=,M=,mod=1e9+;
int n,m,bin[N<<],iv2,iv4,base;
struct Ed{
int s,w;
Ed(int s=,int w=):s(s),w(w) {}
}ed[M];
map<int,int> mp[(<<)+];
int pw(int x,int k)
{int ret=;while(k){if(k&)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=;}return ret;}
int dfs(int S)
{
int s0=S>>n,s1=S&base;
if(mp[s0].count(s1))return mp[s0][s1];
int ret=;
for(int i=;i<=m;i++)
if((ed[i].s|S)==S&&(ed[i].s<<)>S)
ret=(ret+(ll)ed[i].w*dfs(S^ed[i].s))%mod;
return mp[s0][s1]=ret;
}
int main()
{
int tp,t,s1,s2;
n=rdn();tp=rdn();
bin[]=;for(int i=,j=n<<;i<=j;i++)bin[i]=bin[i-]<<;
iv2=pw(,mod-); iv4=pw(,mod-); base=bin[n]-; mp[][]=bin[n];
for(int i=;i<=tp;i++)
{
t=rdn();s1=bin[rdn()-+n]|bin[rdn()-];
ed[++m]=Ed(s1,iv2); if(!t)continue;
s2=bin[rdn()-+n]|bin[rdn()-];
ed[++m]=Ed(s2,iv2);
if(s1&s2)continue;///
ed[++m]=Ed(s1|s2,t==?iv4:mod-iv4);
}
printf("%d\n",dfs(bin[n<<]-));
return ;
}

bzoj 5006(洛谷 4547) [THUWC2017]Bipartite 随机二分图——期望DP的更多相关文章

  1. bzoj5006: [THUWC2017 Bipartite]随机二分图

    某人在玩一个非常神奇的游戏.这个游戏中有一个左右各 nnn 个点的二分图,图中的边会按照一定的规律随机出现. 为了描述这些规律,某人将这些边分到若干个组中.每条边或者不属于任何组 (这样的边一定不会出 ...

  2. 洛谷P3239 [HNOI2015]亚瑟王(期望dp)

    传送门 stdcall大佬好强 期望的姿势不是很高……据大佬说期望有一个线性性质,也就是说可以把每一张牌的期望伤害算出来然后再加起来就是总的期望伤害 因为每一张牌只能用一次,我们设$dp[i]$表示第 ...

  3. 洛谷P1365 WJMZBMR打osu! / Easy——期望DP

    题目:https://www.luogu.org/problemnew/show/P1365 平方和怎样递推? 其实就是 (x+1)^2 = x^2 + 2*x + 1: 所以我们要关注这里的 x — ...

  4. 洛谷 P3239 [HNOI2015]亚瑟王(期望+dp)

    题面传送门 感觉是道挺好的题,可惜当时没写题解来着的? 根据期望的线性公式,我们求出每个卡牌被发动的概率 \(q_i\),然后 \[ans=\sum\limits_{i=1}^np_id_i \] 于 ...

  5. 洛谷 P5249 - [LnOI2019]加特林轮盘赌(期望 dp+高斯消元)

    题面传送门 期望真 nm 有意思,所以蒟蒻又来颓期望辣 先特判掉 \(P_0=0\) 的情况,下面假设 \(P_0\ne 0\). 首先注意到我们每次将加特林对准一个人,如果这个人被毙掉了,那么相当于 ...

  6. [BZOJ 3039&洛谷P4147]玉蟾宫 题解(单调栈)

    [BZOJ 3039&洛谷P4147]玉蟾宫 Description 有一天,小猫rainbow和freda来到了湘西张家界的天门山玉蟾宫,玉蟾宫宫主蓝兔盛情地款待了它们,并赐予它们一片土地. ...

  7. 【THUWC2017】随机二分图(动态规划)

    [THUWC2017]随机二分图(动态规划) 题面 BZOJ 洛谷 题解 如果每天边的限制都是\(0.5\)的概率出现或者不出现的话,可以把边按照二分图左侧的点的编号排序,然后设\(f[i][S]\) ...

  8. bzoj 3680(洛谷1337) 吊打XXX——模拟退火

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3680 https://www.luogu.org/problemnew/show/P1337 ...

  9. bzoj 4816: 洛谷 P3704: [SDOI2017]数字表格

    洛谷很早以前就写过了,今天交到bzoj发现TLE了. 检查了一下发现自己复杂度是错的. 题目传送门:洛谷P3704. 题意简述: 求 \(\prod_{i=1}^{N}\prod_{j=1}^{M}F ...

随机推荐

  1. Linux学习笔记之Linux通过yum安装桌面

    Centos系统最小化安装以后,进入默认是命令行模式,所以需要进一步安装桌面. 1,本文使用的是CentOS 7 Minimal版本. 2,启动linux操作系统,进入后没有图形界面,但是有时候还是希 ...

  2. JS的 instanceof 方法

    http://www.cnblogs.com/jasonxuli/p/6769282.html 这是 2014-12-10 发在 iteye 上的文章 今天突然想起js的原型继承模型和相关的proto ...

  3. BCG控件初步领略

    BCGPVisualStudioGUIDemo 这个界面很不错呀,如果能够实现这种效果,能够解决系列问题 画图程序,这种界面非常先进.用于石材大板等非常优秀. email的效果 这种东西如果效果不错, ...

  4. Java Mail 邮件发送简单封装

    上一篇文章我们用写了一个Java Mail 的Demo,相信你已经可以用那个例子来发送邮件了.但是Demo 有很多的问题. 首先每次发送需要配置的东西很多,包括发件人的邮箱和密码.smtp服务器和SM ...

  5. linux内核源码在线浏览

    1.https://elixir.bootlin.com  (只能搜索函数和宏定义,功能单一) 2.https://lxr.missinglinkelectronics.com (比第一个功能多一些, ...

  6. 框架-spring源码分析(一)

    框架-spring源码分析(一) 参考: https://www.cnblogs.com/heavenyes/p/3933642.html http://www.cnblogs.com/BINGJJF ...

  7. HDU 6053 TrickGCD(莫比乌斯反演)

    http://acm.hdu.edu.cn/showproblem.php?pid=6053 题意:给出一个A数组,B数组满足Bi<=Ai. 现在要使得这个B数组的GCD值>=2,求共有多 ...

  8. Maven简单的配置Junit测试及使用简单的mock

    1.maven依赖配置如下 <dependency> <groupId>org.mockito</groupId> <artifactId>mockit ...

  9. 流行得前端构建工具比较,以及gulp配置

    前端现在三足鼎立的构建工具(不算比较老的ant,yeoman),非fis,grunt,gulp莫属了. fis用起来最简单,我打算自己得项目中使用一下fis. 先说一下gulp安装吧. 第一步:安装n ...

  10. tp5集成淘宝,微信,网易,新浪等第三方登录

    tp5集成淘宝,微信,网易,新浪等第三方登录 一.总结 一句话总结: 接口 链接 实现的话就是这些平台给的一个接口(链接),你通过这些接口登录进去之后,它会给你返回用户名,头像之类的信息,我们的网站存 ...