@codeforces - 913F@ Strongly Connected Tournament
@description@
n 个选手参加了一场竞赛,这场竞赛的规则如下:
1.一开始,所有选手两两之间独立进行比赛(没有平局)。
2.主办方将胜者向败者连边形成 n 个点的竞赛图。
3.主办方对这个竞赛图进行强连通分量缩点。
4.每一个强连通分量内部的选手重复步骤 1~3,直到每一个强连通分量内只剩一个选手。
现已知当 i < j 时,选手 i 战胜选手 j 的概率是 p,请计算比赛次数的期望。
Input‘
第一行包含一个整数 n (2 ≤ n ≤ 2000) — 表示玩家个数。
第二行包含两个整数 a 和 b (1 ≤ a < b ≤ 100) — 表示概率 p = a/b。
Output
输出一行一个整数表示期望,对 998244353 取模。
Examples
Input
3
1 2
Output
4
Input
3
4 6
Output
142606340
Input
4
1 2
Output
598946623
Note
第一组样例答案是 4;
第二组样例答案是 27/7;
第三组样例答案是 56/5。
@solution@
可以发现题目给定的过程其实就是个求解子问题的过程,可以使用 dp。
考虑最暴力的解法:枚举每条边的定向,计算概率与此时的强连通分量,进行 dp 的转移。注意可以转移到自己,概率期望 dp 套路(指转移方程移项)即可。
我们发现,如果要求解自己转移到自己的概率,实际上是求 n 个点连成强连通分量的概率 g[n]。
先一步步来,考虑怎么求这个概率,可以使用套路容斥。
即假如 n 个点连不成强连通分量,我们就枚举拓扑序最前面的强连通分量大小 s。
令 f[n][s] 表示 n 个点的图选出 s 个点使得 s 个点与剩下 n-s 个点之间的连边总是 s 个点连过去的概率,则这个时候出现这种局面的概率为 g[s]*f[n][s],最后 g[n] = 1 - ∑g[s]*f[n][s]。
现考虑怎么求 f[n][s],可以做类似背包 dp 的方法。
假如加入的第 n 个点不在 s 个点之中,则从 f[n-1][s] 转移过来,s 个点要全部向点 n 连边,所以概率为 p^s。
假如加入的第 n 个点在 s 个点之中,则从 f[n-1][s-1] 转移过来,点 n 要向除了选出来的 s 个点的其他点连边,所以概率为 (1-p)^(n-s)。
现在回到一开始的 dp,考虑不是转移到自己的时候(即没有形成强连通)。假如缩点后的图为 A1->A2->...->Am,则对应的概率为 g[A1]*f[n][A1] + g[A2]*f[n-A1][A2] + ...,对应的权值为 dp[A1] + dp[A2] + ...。
我们怎么优化这个 dp 呢?不妨令 h[n] 表示将 n 个点划分成若干强连通分量对应的期望(注意不同于 dp 数组的定义,h 只是“划分”,并没有计算划分出来的强连通分量两两之间的贡献)(划分出来的强连通可以只有一个)。
h 的转移可以通过枚举拓扑序最前的强连通(类似于上面的容斥)。dp 的转移与 h 类似,也是枚举拓扑序最前的强连通。
@accepted code@
#include<cstdio>
const int MAXN = 2000;
const int MOD = 998244353;
int pow_mod(int b, int p) {
int ret = 1;
while( p ) {
if( p & 1 ) ret = 1LL*ret*b%MOD;
b = 1LL*b*b%MOD;
p >>= 1;
}
return ret;
}
int n, a, b, p1[MAXN + 5], p2[MAXN + 5];
int f[MAXN + 5][MAXN + 5], g[MAXN + 5];
int dp[MAXN + 5], h[MAXN + 5];
int main() {
scanf("%d%d%d", &n, &a, &b);
p1[0] = 1, p1[1] = 1LL*a*pow_mod(b, MOD-2)%MOD;
p2[0] = 1, p2[1] = (MOD + 1 - p1[1])%MOD;
for(int i=2;i<=n;i++)
p1[i] = 1LL*p1[i-1]*p1[1]%MOD, p2[i] = 1LL*p2[i-1]*p2[1]%MOD;
f[1][1] = 1;
for(int i=2;i<=n;i++) {
f[i][1] = (1LL*f[i-1][1]*p1[1]%MOD + p2[i-1])%MOD;
for(int j=2;j<=i;j++)
f[i][j] = (1LL*f[i-1][j]*p1[j]%MOD + 1LL*f[i-1][j-1]*p2[i-j]%MOD)%MOD;
}
for(int i=1;i<=n;i++) {
g[i] = 1;
for(int j=1;j<i;j++)
g[i] = (g[i] + MOD - 1LL*g[j]*f[i][j]%MOD)%MOD;
}
h[1] = dp[1] = 0;
for(int i=2;i<=n;i++) {
for(int j=1;j<i;j++)
h[i] = (h[i] + 1LL*g[j]*f[i][j]%MOD*(dp[j] + h[i-j])%MOD)%MOD;
dp[i] = 1LL*(h[i] + 1LL*i*(i-1)/2%MOD)*pow_mod((1 + MOD - g[i])%MOD, MOD-2)%MOD;
h[i] = (h[i] + 1LL*g[i]*dp[i]%MOD)%MOD;
}
printf("%d\n", dp[n]);
}
@details@
一开始把边的数量(即原题目中比赛的数量)统计成点的数量,手玩样例还以为是样例的问题。。。
@codeforces - 913F@ Strongly Connected Tournament的更多相关文章
- 【CodeForces】913 F. Strongly Connected Tournament 概率和期望DP
[题目]F. Strongly Connected Tournament [题意]给定n个点(游戏者),每轮游戏进行下列操作: 1.每对游戏者i和j(i<j)进行一场游戏,有p的概率i赢j(反之 ...
- 【CF913F】Strongly Connected Tournament 概率神题
[CF913F]Strongly Connected Tournament 题意:有n个人进行如下锦标赛: 1.所有人都和所有其他的人进行一场比赛,其中标号为i的人打赢标号为j的人(i<j)的概 ...
- codeforces B. Strongly Connected City(dfs水过)
题意:有横向和纵向的街道,每个街道只有一个方向,垂直的街道相交会产生一个节点,这样每个节点都有两个方向, 问是否每一个节点都可以由其他的节点到达.... 思路:规律没有想到,直接爆搜!每一个节点dfs ...
- Codeforces913F. Strongly Connected Tournament
n<=2000个人参加比赛,这样比:(这里的序号没按题目的)1.两两比一场,比完连个图,边i->j表示i赢了j.2.连完那个图强联通分量缩起来,强连通分量内继续比,即强连通分量递归进行1. ...
- Strongly Connected Tournament
题解: 有一个很重要的性质就是 对于一张完全强联通图来说 一定有一个强联通分量入度为0(或者出度为0) 然后就一些计数题的基本套路 https://www.cnblogs.com/onioncyc/p ...
- PTA Strongly Connected Components
Write a program to find the strongly connected components in a digraph. Format of functions: void St ...
- algorithm@ Strongly Connected Component
Strongly Connected Components A directed graph is strongly connected if there is a path between all ...
- cf475B Strongly Connected City
B. Strongly Connected City time limit per test 2 seconds memory limit per test 256 megabytes input s ...
- Strongly connected(hdu4635(强连通分量))
/* http://acm.hdu.edu.cn/showproblem.php?pid=4635 Strongly connected Time Limit: 2000/1000 MS (Java/ ...
随机推荐
- 使用Jedis操作Redis-使用Java语言在客户端操作---List类型
在Redis中,List类型是按照插入顺序排序的字符串链表.和数据结构中的普通链表一样,我们可以在其头部(left)和尾部(right)添加新的元素.在插入时,如果该键并不存在,Redis将为该键创建 ...
- INotitypropertyChanged
WPF数据绑定(要是后台类对象的属性值发生改变,通知在“client界面与之绑定的控件值”也发生改变须要实现INotitypropertyChanged接口) MainWindow.xaml < ...
- oracle常用的时间格式转换
1:取得当前日期是本月的第几周 select to_char(sysdate,'YYYYMMDD W HH24:MI:SS') from dual; TO_CHAR(SYSDATE,'YY') se ...
- 洛谷 P2356 弹珠游戏
题目链接:https://www.luogu.org/problemnew/show/P2356 题目 题目描述 MedalPluS 和他的小伙伴 NOIRP 发掘了一个骨灰级别的游戏——超级弹珠. ...
- LUOGU P1512 伊甸园日历游戏
题目描述 Adam和Eve玩一个游戏,他们先从1900.1.1到2001.11.4这个日期之间随意抽取一个日期出来.然后他们轮流对这个日期进行操作: 1 : 把日期的天数加1,例如1900.1.1变到 ...
- 贝叶斯--旧金山犯罪分类预测和电影评价好坏 demo
来源引用:https://blog.csdn.net/han_xiaoyang/article/details/50629608 1.引言 贝叶斯是经典的机器学习算法,朴素贝叶斯经常运用于机器学习的案 ...
- intellij idea cpu占用率太大太满 运行速度太慢解决方案
1.关掉代码检查. setting -> Editor -> Inspections,把右面方框框里的对勾全去掉,或者根据需要去掉.原理是关闭不必要的代码检查,提高速度. 2.关掉多余的插 ...
- 洛谷 P1266 速度限制 最短路+SPFA算法
目录 题面 题目链接 题目描述 输入输出格式 输入格式 输出格式 输入输出样例 输入样例 输出样例 说明 思路 AC代码 题面 题目链接 P1266 速度限制 题目描述 在这个繁忙的社会中,我们往往不 ...
- 阿里云linux服务器到期后续费,网站打不开解决方法之一
续费后打不开网站,可能会出现不同情况,这里只记录我遇到的问题 问题描述:服务器到期后续费,网站打不开. 解决尝试: 1.重启服务器nginx /etc/init.d/nginx restart ...
- 为什么要用Spring的依赖注入
最近写了一些Spring项目,用到了依赖注入,但是不知道为甚么要用,后来在知乎上看了一些大家的回答,觉得很精辟,遂简单总结一下. 主要是实现类之间的解耦,假如A类依赖B类,在实例化A类的话也要new一 ...