1630 B君的竞技场
原题连接:
https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1630
概率题。纯数学。
题目中的四个要求:
我们将竞技场规则简化如下:
1. 每个人进入竞技场后,会等概率随机匹配一个人,匹配到的人与当前胜利和失败场数无关。
2. 胜利达到x场,或失败达到y场后,退出竞技场,根据退出时的胜利场数获得奖励,不能中途放弃。
3. 水平高的选手,总能战胜水平低的选手,不存在水平相等的人。
4. 竞技场有无穷多的人。
因为题目给定无穷的人数,其实暗示人数不重要。可以某种方法消去
n
的影响
我们设总人数为:n
因为没有实力相同的两个人。所以每个人相对实力是确定的。(也就是说实力排名是确定的)
给出
n
个实力级别:
1,2,3,4,5,6,....n
那么
b
君的实力级别为 i 时她的胜场概率为:
P(i)=i−1n
设 B君的胜场概率实为 P(i) 时,得分期望为 E(P(i))
则B君的实际望为:
answer=1n∑i=1nE(P(i))=∑i=1n1n∗E(P(i))=∑i=1n1n∗E(i−1n)=∑i=0n−11n∗E(in)
所以,
answer
等于
n
趋近于∞ 时候的答案:
answer=limn−>∞∑i=0n−11n∗E(in)
在任何一本高数书上都可以找到计算上面和式的方法。
对于一般的积分计算,等效于把区间无限微分后得到的答案。
例如:
∫baf(x) dx
如果对于 x∈[a,b] ,函数 f(x) 都是有意义的
我们把区间
[a,b]
分割为
n
分
当n 足够大时。对于每一小段。我们认为
f(x)
变化很小。
此时第
i
小段。与x 轴和曲线
f(x)
围成的面积近似为(
n−>∞
时可以认为相等):
b−anf((i−1)(b−a)n)
所以:
∫baf(x) dx=limn−>∞∑i=1nb−anf((i−1)(b−a)n)=limn−>∞∑i=0n−1b−anf(i∗(b−a)n)
所以:
answer=∫10E(p) dp=limn−>∞∑i=0n−11nE(in)
p
是b君每一场比赛胜利的概率。
当b君每场比赛胜利概率为 p 时。他得分的期望分为两部分。
第一部分:最后一场比赛胜利。总胜利场次x。退出游戏
第二部分:最后一场比赛失败。总是败场次y。退出游戏
注意。退出游戏的原因要么因为失败太多。要么因为胜利太多。
对于第一部分。必然胜利了x场。枚举失败场次,记 失败了
k
场:
则。这部分的贡献为:
∑0<=k<ypx(1−p)k(x+k−1k)
上面的公式可以理解为:当我们比赛 x+k 场时。最后一场比赛必须胜利。那么失败场次可供选择的位置只有 x+k−1 个
同理。记
t
胜利场次。第二部分的贡献为
∑0<=t<xpt(1−p)y(y+t−1t)
所以 E(p) 有:
E(p)=∑0<=k<ypx(1−p)k(x+k−1k)+∑0<=t<xpt(1−p)y(y+t−1t)
所以:
answer=∫10E(p) dpE(p)=∑0<=k<ypx(1−p)k(x+k−1k)+∑0<=t<xpt(1−p)y(y+t−1t)
可以用 辛普森积分 的模版计算上面在区间 [0,1] 上的积分
对于组合数可以利用帕斯卡公式求的:
(nk)=(n−1k)+(n−1k−1)
下面是AC代码
#include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std;
typedef long long LL;
const LL N=10000;
LL C[50][50]={1};
LL W[50][50];
LL x,y;
void init()
{
for(int n=1;n<41;n++)
{
C[n][0]=1;
for(int k=1;k<=n;k++)
{
C[n][k]=C[n-1][k-1]+C[n-1][k];
}
}
}
double pow(double P,LL b)
{
double ans=1;
while(b)
{
if(b&1)
ans*=P;
b>>=1;
P*=P;
}
return ans;
}
double f( double P)
{
double ans=0;
for(LL j=0;j<y;j++)
{
ans+=(double)(x*W[x][j])*pow(P,x)*pow(1-P,j);
}
for(LL j=0;j<x;j++)
{
ans+=(double)(j*W[j][y])*pow(P,j)*pow(1-P,y);
}
return ans;
}
double simpson(double a,double b,LL n)
{
const double h=(b-a)/n;
double ans=f(a)+f(b);
for(int i=1;i<n;i+=2)ans+=4*f(a+i*h);
for(int i=2;i<n;i+=2)ans+=2*f(a+i*h);
return ans*h/3;
}
int main ()
{
init();
scanf("%lld %lld",&x,&y);
for(LL j=0;j<y;j++)
W[x][j]=C[x+j-1][j];
for(LL j=0;j<x;j++)
W[j][y]=C[y+j-1][j];
printf("%lf\n",simpson(0,1,N));
return 0;
}