题意
我们将竞技场规则简化如下:
1. 每个人进入竞技场后,会等概率随机匹配一个人,匹配到的人与当前胜利和失败场数无关。
2. 胜利达到x场,或失败达到y场后,退出竞技场,根据退出时的胜利场数获得奖励,不能中途放弃。
3. 水平高的选手,总能战胜水平低的选手,不存在水平相等的人。
4. 竞技场有无穷多的人。
B君并不知道自己的水平,你可以认为B君的水平是在所有人中的等概率随机。
B君想知道自己退出时期望胜利场数是多少。
题解
对于这种随机的东西。。表示没什么概念
Q:为什么这个东西不能按50%胜率来算(这个傻逼问题就是我问的)
A:因为对于这个题目,有n个人,你的实力水平在第2,和在第
(n−1)
(
n
−
1
)
,两者的期望胜场数是没有联系的,所以不可以
Q:样例解释
A:没有。。
怎么做?
我们考虑,题目的意思就是胜率是等概率随机的
如果我们知道了一个胜率p,那么我们就可以DP出答案,
f[i][j]
f
[
i
]
[
j
]
表示赢了i场,输了j场的概率。
f[i][j]=f[i−1][j]∗(1−p)+f[i][j−1]∗p
f
[
i
]
[
j
]
=
f
[
i
−
1
]
[
j
]
∗
(
1
−
p
)
+
f
[
i
]
[
j
−
1
]
∗
p
这样的话,我们就可以得到答案了
但是p是不固定的,但是我们知道他在
[0,1]
[
0
,
1
]
里面随机分布
于是我们可以先用递推式,可以得到一个
f[i][j]
f
[
i
]
[
j
]
关于p的多项式
然后就是一个积分问题
求一个导数就可以了
因为项数只有类似于
xn
x
n
的形式
直接用
xn−−−−>nxn−1
x
n
−
−
−
−
>
n
x
n
−
1
就可以得到导数了
CODE:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long double LB;
const int N=25;
int x,y;
LB a[5],b[5];//转移的多项式
LB f[N][N][N*2];//输了i场,赢了j场的多项式
void add (int x,int y,LB xx[],LB yy[])
{
f[x][y][0]=max(f[x][y][0],xx[0]+yy[0]-1);
for (int u=1;u<=xx[0];u++)
for (int i=1;i<=yy[0];i++)
f[x][y][u+i-1]=f[x][y][u+i-1]+xx[u]*yy[i];
}
LB getpre(int x,int y)
{
LB lalal=0;
for (int u=1;u<=f[x][y][0];u++)
lalal=lalal+f[x][y][u]/u;
return lalal;
}
int main()
{
scanf("%d%d",&x,&y);
f[0][0][0]=f[0][0][1]=1;
a[0]=2;a[1]=0;a[2]=1;
b[0]=2;b[1]=1;b[2]=-1;
for (int u=0;u<y;u++)
for (int i=0;i<x;i++)
{
if (u>0) add(u,i,f[u-1][i],b);
if (i>0) add(u,i,f[u][i-1],a);
}
LB ans=0;
for (int u=0;u<y;u++)
{
add(u,x,f[u][x-1],a);
ans=ans+getpre(u,x)*x;
}
for (int u=0;u<x;u++)
{
add(y,u,f[y-1][u],b);
ans=ans+getpre(y,u)*u;
}
printf("%.10Lf\n",ans);
return 0;
}