我概率期望真是垃圾……,这题搞了两个钟头……

题意

有\(n\)个人,\(m\)个浴室,每个浴室里有\(a_i\)个浴缸。每个人会等概率随机选择一个浴室,然后每个浴室中尽量平分到每个浴缸。问期望最长排队队伍长度是多少?

解题思路

我看网上的题解都是直接\(DP\)期望,然而本蒟蒻看不懂那个递推式是什么鬼……有没有\(dalao\)来解释一下啊……

付一下别人的题解,摘自https://www.cnblogs.com/LzyRapx/p/7692702.html

用状态$ dp[i][j][k] \(表示还剩\) i$ 间浴室,还剩 \(j\) 个人,之前最长队伍的长度为 \(k\) 的期望最长队伍长度。

那么状态转移方程为:

\[dp[i][j][k]=∑^m_{i=1}∑^n_{j=0}∑^n_{k=1}∑^j_{c=1}(dp[i−1][j−c][max(k,(c+a[i]−1)/a[i])]\times
(i−1)^{j−c}/i^j \times (j,c))
\]

其中 \(c\) 是枚举当前去第 \(j\) 间浴室的人数。

那么答案就是$ dp[m][n][0]$ 。

----伪分割线----

下面是我自己的概率做法。

我们令\(dp[i][j][k]\)表示已经选了\(i\)个浴室,还剩\(j\)个人,最长长度为\(k\)的概率。注意下标意义的定义与上面的不一样。

那么我们可以得到状态转移方程:

\[dp[i+1][j-c][max(k, \frac{c+a[i+1]-1}{a[i+1]})] += dp[i][j][k]\times {j \choose c} / m^c
\]

这里感谢\(PSCdalao\)帮我斧正这个方程,并阐述了为什么是除以\(m^c\)。

下面我们解释这个方程的意义。

现在在状态\(dp[i][j][k]\),那么我们可以从剩下\(j\)个人中,选出\(c\)个。这时候下标就变为了\(dp[i+1][j-c][max(k, \frac{c+a[i+1]-1}{a[i+1]})]\)。而从前一个状态转到这一个方案的概率就是\({j \choose c} / m^c\)(从\(j\)个人中选\(c\)个,而这\(c\)个人本来可以有\(m^c\)种选法)。我们再来仔细看一下为什么是\(m^c\)而不是\((m-i)^c\)。

我们把n个人分到m个澡堂的某种分法的概率应当为

\[\frac{{n\choose p_1}{n-p_1\choose p_2}{n-p_1-p_2\choose p_3}...}{m^n}
\]

然后我们拆开分别乘在每一步中,就成了

\[\frac{{n\choose p_1}}{m^{p_1}} \times \frac{{n-p_1\choose p_2}}{m^{p_2}} \times \frac{{n-p_1-p_2\choose p_3}}{m^{p_3}}...
\]

所以就有方程中的“\(/m^c\)”。

同时,我们可以看出,我们同样可以先求出方案数,最后再除以\(m^c\)。(感谢\(DYTdalao\)提供这个好主意)

到这里,我们求出了概率。最后把每一个概率乘以长度,累加就好了。

不要问我精度问题,反正全部开\(double\),然后什么都不管就可以了QwQ

参考程序

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; const int Maxn = 60;
int n, m, a[ Maxn ];
double dp[ Maxn ][ Maxn ][ Maxn ], C[ 60 ][ 60 ]; double Power( double x, int y ) {
if( y == 0 ) return 1.0;
double t = Power( x, y / 2 );
t = t * t;
if( y % 2 == 1 ) t = t * x;
return t;
} void init() {
memset( C, 0, sizeof( C ) );
C[ 0 ][ 0 ] = 1.0;
for( int i = 1; i <= 50; ++i ) {
C[ i ][ 0 ] = 1.0;
for( int j = 1; j <= i; ++j ) C[ i ][ j ] = C[ i - 1 ][ j - 1 ] + C[ i - 1 ][ j ];
}
return;
} int main() {
init();
memset( dp, 0, sizeof( dp ) );
scanf( "%d%d", &n, &m );
dp[ 0 ][ n ][ 0 ] = 1.0;
for( int i = 1; i <= m; ++i ) scanf( "%d", &a[ i ] );
for( int i = 0; i < m - 1; ++i )
for( int j = 0; j <= n; ++j )
for( int k = 0; k <= n; ++k )
for( int c = 0; c <= j; ++c )
dp[ i + 1 ][ j - c ][ max( k, ( c + a[ i + 1 ] - 1 ) / a[ i + 1 ] ) ] +=
dp[ i ][ j ][ k ] * C[ j ][ c ] / Power( m * 1.0, c );
for( int j = 0; j <= n; ++j )
for( int k = 0; k <= n; ++k )
dp[ m ][ 0 ][ max( k, ( j + a[ m ] - 1 ) / a[ m ] ) ] += dp[ m - 1 ][ j ][ k ] * 1.0 / Power( m * 1.0, j );
double ans;
for( int i = 0; i <= n; ++i )
ans += i * dp[ m ][ 0 ][ i ];
printf( "%.10lf\n", ans );
return 0;
}

CodeForces - 28C Bath Queue 概率与期望的更多相关文章

  1. Codeforces 28C Bath Queue 【计数类DP】*

    Codeforces 28C Bath Queue LINK 简要题意:有 n 个人等概率随机进入 m 个房间,一个房间可以有多个人,第 i 个房间有 ai 个水龙头,在一个房间的人要去排队装水,他们 ...

  2. Codeforces #28 C.Bath Queue (概率dp)

    Codeforces Beta Round #28 (Codeforces format) 题目链接: http://codeforces.com/contest/28/problem/C 题意: 有 ...

  3. Codeforces 1009E Intercity Travelling | 概率与期望

    题目链接 题目大意: 一个人要从$A$地前往$B$地,两地相距$N$千米,$A$地在第$0$千米处,$B$地在第$N$千米处. 从$A$地开始,每隔$1$千米都有$\dfrac{1}{2}$的概率拥有 ...

  4. 【CodeForces】913 F. Strongly Connected Tournament 概率和期望DP

    [题目]F. Strongly Connected Tournament [题意]给定n个点(游戏者),每轮游戏进行下列操作: 1.每对游戏者i和j(i<j)进行一场游戏,有p的概率i赢j(反之 ...

  5. 概率及期望DP小结

    资源分享 26 个比较概率大小的问题 数论小白都能看懂的数学期望讲解 概念 \(PS\):不需要知道太多概念,能拿来用就行了. 定义 样本(\(\omega\)):一次随机试验产生的一个结果. 样本空 ...

  6. 【算法学习笔记】概率与期望DP

    本文学习自 Sengxian 学长的博客 之前也在CF上写了一些概率DP的题并做过总结 建议阅读完本文再去接着阅读这篇文章:Here 前言 单纯只用到概率的题并不是很多,从现有的 OI/ACM 比赛中 ...

  7. 【BZOJ-3450】Tyvj1952Easy 概率与期望DP

    3450: Tyvj1952 Easy Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 468  Solved: 353[Submit][Status] ...

  8. 【BZOJ-4008】亚瑟王 概率与期望 + DP

    4008: [HNOI2015]亚瑟王 Time Limit: 20 Sec  Memory Limit: 512 MBSec  Special JudgeSubmit: 832  Solved: 5 ...

  9. BZOJ_4872_[Shoi2017]分手是祝愿_概率与期望

    BZOJ_4872_[Shoi2017]分手是祝愿_概率与期望 Description Zeit und Raum trennen dich und mich. 时空将你我分开.B 君在玩一个游戏,这 ...

随机推荐

  1. Intellij IDEA神器好用到飞起来的配置

    ​   IDEA 全称 IntelliJ IDEA,是java编程语言开发的集成环境. IntelliJ在业界被公认为最好的java开发工具之一, 尤其在智能代码助手.代码自动提示.重构.J2EE支持 ...

  2. unittest之三:字符串与列表的相互转换与分离数据时的应用

    一.分离数据时,需读取文档中存储的数据,但TXT文件的数据读取出来的类型为列表,而测试用例中断言的时候验证的是字符串,所以需要将列表转为字符串 #1字符串————>列表 str1='hello ...

  3. Docker 构建私有镜像仓库

    在使用Docker一段时间后,往往会发现手头积累了大量的自定义镜像文件,这些文件通过公有仓库进行管理并不方便,另外有时候只是希望在内部用户之间进行分享,不希望暴露出去.这种情况下,就有必要搭建一个本地 ...

  4. tomcat搭建webDav

    工具准备: tomcat-8.0.53 前言:由于工作需要,希望自己搭建webdav服务端,刚开始用windowsServer 2012 R2版本自带的IIS服务器搭建,搭建好之后浏览器可以访问,但无 ...

  5. js小数和百分数的转换

    一.百分数转化为小数 function toPoint(percent){ var str=percent.replace("%",""); str= str/ ...

  6. MySQL主从延时这么长,要怎么优化?

    MySQL主从复制,读写分离是互联网常见的数据库架构,该架构最令人诟病的地方就是,在数据量较大并发量较大的场景下,主从延时会比较严重. 为什么主从延时这么大? 答:MySQL使用单线程重放RelayL ...

  7. NumPy 简介及安装

    NumPy(Numerical Python) 是 Python 语言的一个扩展程序库,支持大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库.NumPy 的前身 Numeric 最早是 ...

  8. zabbix监控,微信报警

    微信告警 访问这个地址创建企业微信   https://work.weixin.qq.com/  

  9. xml配置文件命名空间学习

    xmlns(XML Namespaces的缩写)是一个属性,是XML(标准通用标记语言的子集)命名空间.作用是赋予命名空间一个唯一的名称. 编写Spring或者Maven或者其他需要用到XML文档的程 ...

  10. hive创建分区表

    #创建分区表CREATE TABLE if not exists data_center.test_partition (id int,name string,age int)PARTITIONED ...