题目
思路
期望dp。
设
a
i
,
j
a_{i,j}
ai,j为前i个人中,第j个人活到最后的情况。
显然有:
a
i
,
j
=
P
∗
a
i
−
1
,
j
−
1
+
(
1
−
P
)
∗
a
i
,
j
−
1
,
1
<
=
i
<
=
n
,
1
<
=
j
<
=
i
a_{i,j}=P*a_{i-1,j-1}+(1-P)*a_{i,j-1},1<=i<=n,1<=j<=i
ai,j=P∗ai−1,j−1+(1−P)∗ai,j−1,1<=i<=n,1<=j<=i
同时有:
∑
j
=
1
i
a
i
,
j
=
1
\sum^{i}_{j=1}a_{i,j}=1
∑j=1iai,j=1
那么这里一共n个方程,全部高斯消元?
TLE妥妥地
所以我们不能用高斯消元,那么我们如何提速呢?
n只有
1
0
4
10^4
104,所以可以n方算法,这么说这里计算方程只能O(n)了?
没错,当然是O(n)!
按循环顺序,显然方程第一项是个常数了,我们只需要考虑后面的,运用递归知识(这里O(n)),我们可以求出一个这样的柿子:
x
∗
a
i
,
1
+
y
=
1
x*a_{i,1}+y=1
x∗ai,1+y=1,进一步可得
a
i
,
1
a_{i,1}
ai,1,这里就可以递推出
a
i
,
2
…
…
a
i
,
i
a_{i,2}……a_{i,i}
ai,2……ai,i.
不要忘记特判
P
P
P为0的情况。
code:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
using namespace std;
double p,a[10010],b[10010],c,d,lc,ld;
int n,k;
void f(int x)
{
if (x==1)
{
c=1,d=0,
lc=1,ld=0;
return;
}
f(x-1);
c=(1-p)*c;
d=p*b[x]+(1-p)*d;
lc+=c,ld+=d;
return;
}
int main()
{
cin>>p>>n>>k;
if (p==0)//加特林瓦特了
{
cout<<(n<=1);
return 0;
}
b[2]=a[1]=1;
for (int i=2;i<=n;i++)
{
f(i);
a[1]=(1-ld)/lc;
for (int j=2;j<=i;j++) a[j]=p*b[j]+(1-p)*a[j-1];
for (int j=2;j<=i+1;j++) b[j]=a[j-1];
}
printf("%.12lf",a[k]);
return 0;
}