F

对于一张比赛图,经过缩点,会得到dag,且它一定是transitive的,因此我们能直接把比赛图缩成一个有向链。链头作为一个强连通分量,里面的所有点都是胜利的

定义F(win)表示win集合作为赢家的概率,我们有

\[ans=\sum_{win\in all} F(win)|win|
\]

显然win集合内的点构成一个强连通分量,并作为链头。win集合内的点一定向集合外的每个点连边

考虑如何求解F(win)

我们定义H(win)表示在win集合内的点构成的子图中,win集合成为一个强连通分量的概率。

容易发现这个子图仍然满足比赛图的性质!

考虑去掉win不是一个强连通分量的情况,那么一定存在win的非空真子集sub,sub是子图链头,此时 sub内的所有点 向 win/sub内的所有点 连边。我们得到

\[H(win)=1-\sum_{sub\subset win,sub\ne \phi}H(sub)G(sub,win/sub)
\]

其中\(G(x,y)\)表示x集合向y集合的点直接连边的概率

求出的H可以推F了,win想每个集合外的点连边

\[F(win)=G(win,all/win)H(win)
\]

接下来考虑如何求出G

原题n=14,可以接受\(O(n3^{n})\)的做法,我们预处理出每个点连向一个集合的概率\(f(i,s)\),那么每次调用G的时间是\(O(n)\)

题解提供了一个\(O(3^{n})\)的方法,让每次调用G是\(O(1)\)的

首先是预处理每个点连向集合的概率,我们处理出每个数最高位的1的位置,就可以在\(O(n2^{n})\)递推出\(f(i,s)\)

考虑把n分成大小不超过1的两个集合left,right

现在有一个询问\(G(x,y)\),x,y分别在left和right集合内存在一部分lx,ly,rx,ry,答案是

\(G(x,y)=G(lx,ly)G(lx,ry)G(rx,ly)G(rx,ry)\)

这四部分贡献可以分别预处理,由于left和right的大小只有原来的一半,每个数组处理的时间只有\(O(n2^{n})\)

tips:经可可提醒,这个优化套路在[ctsc2017]吉夫特,有机会去做一下

#include<bits/stdc++.h>

using namespace std;

#define r(x) read(x)
#define gc c=getchar()
#define ll long long
#define ffl fflush(stdout)
#define it set<string>::iterator const int N1=(1<<14)+5, p=1e9+7, maxn=2e6;
const int M1=(1<<7)+5;
const ll inf=0x3f3f3f3f3f3f3fll;
template<typename T>
inline void read(T &x){
x=0;T k=1;char gc;
while(!isdigit(c)){if(c=='-')k=-1;gc;}
while(isdigit(c)){x=x*10+c-'0';gc;}x*=k;
} int n,m,L,R;
int a[16],bcnt[N1],lg[N1];
ll F[N1],f[16][N1],H[N1],inv[maxn+5];
ll gl[M1][M1],gr[M1][M1],glr[M1][M1],grl[M1][M1]; ll G(int X,int Y){
int lx=X&L, rx=(X&R)>>m, ly=Y&L, ry=(Y&R)>>m;
return gl[lx][ly]*gr[rx][ry]%p*glr[lx][ry]%p*grl[rx][ly]%p;
}
// inline int lowbit(int x){ return x&(-x); } int main(){
// freopen("1.in","r",stdin);
// freopen(".out","w",stdout);
// int Te; read(Te);
// while(Te--) printf("%lld\n",solve());
read(n);
if(n==1){ puts("1"); return 0; }
for(int i=0;i<n;i++) read(a[i]);
inv[1]=1;
for(int i=2;i<=maxn;i++) inv[i]=1ll*(p-p/i)*inv[p%i]%p;
int all=(1<<n)-1;
lg[1]=0;
for(int i=2;i<(1<<n);i++) lg[i]=lg[i>>1]+1;
for(int s=1;s<(1<<n);s++) bcnt[s]=bcnt[s>>1]+(s&1);
// for(int s=0;s<(1<<n);s++){
// for(int i=0;i<n;i++) if( !((1<<i)&s) ){
// f[i][s]=1;
// for(int j=0;j<n;j++) if((1<<j)&s) (f[i][s]*=a[i]*inv[a[i]+a[j]]%p)%=p;
// }
// }
//每次去掉highbit 也就是lg 可以O(n*2^n)内递推
for(int i=0,j;i<n;i++){
f[i][0]=1;
for(int s=1;s<(1<<n);s++) if(!((1<<i)&s)){
j=lg[s];
f[i][s]=f[i][s^(1<<j)]*a[i]%p*inv[a[i]+a[j]]%p;
}
} m=(n+1)/2; L=(1<<m)-1; R=all^L;
for(int lx=0;lx<=L;lx++){
int s=L^lx;
for(int t=s;;t=(t-1)&s){
gl[lx][t]=1;
for(int i=0;i<m;i++) if((1<<i)&lx)
(gl[lx][t]*=f[i][t])%=p;
if(!t) break;
}
}
for(int rx=0;rx<=(R>>m);rx++){
int s=(R>>m)^rx;
for(int t=s;;t=(t-1)&s){
gr[rx][t]=1;
for(int i=0;i<n-m;i++) if((1<<i)&rx)
(gr[rx][t]*=f[i+m][t<<m])%=p;
if(!t) break;
}
}
for(int lx=0;lx<=L;lx++){
for(int ry=0;ry<=(R>>m);ry++){
glr[lx][ry]=1;
for(int i=0;i<m;i++) if((1<<i)&lx)
(glr[lx][ry]*=f[i][ry<<m])%=p;
}
}
for(int rx=0;rx<=(R>>m);rx++){
for(int ly=0;ly<=L;ly++){
grl[rx][ly]=1;
for(int i=0;i<n-m;i++) if((1<<i)&rx)
(grl[rx][ly]*=f[i+m][ly])%=p;
}
} ll ans=0;
for(int win=1;win<(1<<n);win++){
H[win]=1; ll tmp;
for(int sub=(win-1)&win;sub;sub=(sub-1)&win){
// tmp=1;
// for(int i=0;i<n;i++) if((1<<i)&sub){
// (tmp*=f[i][win^sub])%=p;
// }
H[win]=(H[win]-H[sub]*G(sub,win^sub)%p+p)%p;
}
// tmp=1;
// assert(bcnt[win]!=2||H[win]==0);
// for(int i=0;i<n;i++) if((1<<i)&win) (tmp*=f[i][all^win])%=p;
// F[win]=tmp*H[win]%p;
F[win]=G(win,all^win)*H[win]%p;
(ans+=F[win]*bcnt[win]%p)%=p;
}
printf("%lld\n",ans);
return 0;
}

CF1556F Sports Betting (状压枚举子集DP)的更多相关文章

  1. [POJ1681]Painter's Problem(高斯消元,异或方程组,状压枚举)

    题目链接:http://poj.org/problem?id=1681 题意:还是翻格子的题,但是这里有可能出现自由变元,这时候枚举一下就行..(其实这题直接状压枚举就行) /* ━━━━━┒ギリギリ ...

  2. HDU2489【状压枚举】

    题意: 给你n个点的图,然后让你在图里挑m个点,达到sumedge/sumnode最小 思路: 由于数据范围小,状压枚举符合m个点的状态,我是用vactor存了结点位置,也记录了结点的sum值,然后跑 ...

  3. POJ3734【状压枚举】

    题意: 给你两个01矩阵,去掉矩阵B的某些行和某些列,问处理后的矩阵B能否变成矩阵A: 思路: 数据较小,状压枚举B矩阵列的数量=A矩阵列的数量时的状态,然后搞定了列,贪心判断B矩阵的行就好了: #i ...

  4. HDU 4336-Card Collector(状压,概率dp)

    题意: 有n种卡片,每包面里面,可能有一张卡片或没有,已知每种卡片在面里出现的概率,求获得n种卡片,需要吃面的包数的期望 分析: n很小,用状压,以前做状压时做过这道题,但概率怎么推的不清楚,现在看来 ...

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

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

  6. [WC2018]州区划分(状压,子集卷积)

    [洛谷题面]https://www.luogu.org/problemnew/show/P4221 首先考虑判定一个子图是否合法: (1)连通:并查集判断即可. (2)没有欧拉回路:存在欧拉回路的条件 ...

  7. POJ - 1753 Flip Game(状压枚举)

    https://vjudge.net/problem/POJ-1753 题意 4*4的棋盘,翻转其中的一个棋子,会带动邻接的棋子一起动.现要求把所有棋子都翻成同一种颜色,问最少需要几步. 分析 同一个 ...

  8. UVA 11600-Masud Rana(状压,概率dp)

    题意: 有n个节点的图,开始有一些边存在,现在每天任意选择两点连一条边(可能已经连过),求使整个图联通的期望天数. 分析: 由于开始图可以看做几个连通分量,想到了以前做的一个题,一个点代表一个集合(这 ...

  9. UVA - 10817 Headmaster's Headache (状压类背包dp+三进制编码)

    题目链接 题目大意:有S门课程,N名在职教师和M名求职者,每名在职教师或求职者都有自己能教的课程集合以及工资,要求花费尽量少的钱选择一些人,使得每门课程都有至少两人教.在职教师必须选. 可以把“每个课 ...

随机推荐

  1. Solution -「USACO 2020.12 P」Spaceship

    \(\mathcal{Description}\)   Link.   Bessie 在一张含 \(n\) 个结点的有向图上遍历,站在某个结点上时,她必须按下自己手中 \(m\) 个按钮中处于激活状态 ...

  2. Java 线程的 5 种状态

    线程状态图: 线程共包括以下 5 种状态: 1. 新建状态(New): 线程对象被创建后,就进入了新建状态.例如,Thread thread = new Thread(). 2. 就绪状态(Runna ...

  3. .NET core实现一个简易的事件协调器(saga)

    在领域驱动设计中,由于领域边界的存在,以往的分层设计中业务会按照其固有的领域知识被切分到不同的限界中,并且引入了领域事件这一概念来降低单个业务的复杂度,通过非耦合的事件驱动来完成复杂的业务.但是事件驱 ...

  4. Zookeeper应用之一:数据发布与订阅初体验

    Zookeeper到底是什么?可以从Zookeeper提供的功能来理解.本篇小作文就是使用其提供的功能之一:数据发布与订阅. 需求:服务端开启多个实例提供服务,客户端使用服务.如果服务端某个服务下线或 ...

  5. log4j的替换方案

    去年12月份,随着log4j暴露出高危漏洞,对于 Java 开发人员来说不是一个好消息,对于 Ops 来说更是如此.前者必须使用固定的 Log4J 版本重新打包他们的应用程序,而后者必须重新部署.但对 ...

  6. 「BUAA OO Pre」 Pre 2总结回顾概览

    「BUAA OO Pre」 Pre 2总结回顾概览 目录 「BUAA OO Pre」 Pre 2总结回顾概览 Part 0 前言 写作背景 定位 您可以在这里期望获得 您在这里无法期望获得 对读者前置 ...

  7. 【转】浅谈 Integer 类

    突然发现自己对Integer i = 10;这种语法不太明白,于是乎有了这篇文章,那么在讲解 Integer 之前,我们先看下面这段代码: 1 2 3 4 5 6 7 8 9 10 11 12 13 ...

  8. Django模板的继承与模板的导入

    目录 一:模版的继承 1.什么是模板继承? 2.使用继承流程原理 3.模板继承语法 二:模板的继承使用 1.案例需求 2.总结模板继承 三:模版的导入 1.模板导入 2.模板导入格式 3.模板导入使用 ...

  9. Java中读写锁的介绍

    读写锁的简单介绍 所谓的读写锁,就是将一个锁拆分为读锁和写锁两个锁,然后你加锁的时候,可以加读锁,也可以加写锁. ReentrantLock lock=new ReentrantLock(); loc ...

  10. SqlServer 局域网内不能连接对方数据库?

    一直都是连接的远程测试服务器的数据库,今天想把自己的数据库开放出来让公司同事连接,竟然连接失败!转了很大一个圈终于搞定了. 接下来就把这次心历路程发出来,希望能帮助到有需要的博友. PS: 我和同事的 ...