一、题目
二、解法
设
f
[
i
]
[
j
]
f[i][j]
f[i][j]为听完前
i
i
i个音频需要
j
j
j秒的概率,转移如下:
f
[
i
]
[
j
]
=
f
[
i
−
1
]
[
j
−
k
]
×
(
1
−
p
[
i
]
)
k
−
1
×
p
[
i
]
f[i][j]=f[i-1][j-k]\times(1-p[i])^{k-1}\times p[i]
f[i][j]=f[i−1][j−k]×(1−p[i])k−1×p[i]其中
k
=
t
[
i
]
k=t[i]
k=t[i]的情况需要特殊处理,后面的
p
[
i
]
p[i]
p[i]就不需要乘上去了,暴力转移不足以通过本题,观察方程,发现可以用前缀和优化,我们单独把
k
=
t
[
i
]
k=t[i]
k=t[i]的情况拿出来考虑就行了,时间复杂度
O
(
n
T
)
O(nT)
O(nT)
答案的计算有所考究,每个磁带的贡献都为 1 1 1,所以我们直接把 d p dp dp时所以的 f f f值求和就行了,注意不能够求和 ∑ f [ i ] [ T ] × i \sum f[i][T]\times i ∑f[i][T]×i,虽然期望=概率×贡献,但是听完磁带不一定要用完所有时间,我们只能使用第一种方法。
#include <cstdio>
#include <cmath>
const int M = 5005;
#define db double
int read()
{
int x=0,flag=1;
char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,m,t[M];db sum,ans,lst,p[M],f[M][M];
int main()
{
n=read();m=read();
for(int i=1;i<=n;i++)
{
scanf("%lf",&p[i]);
p[i]/=100;
t[i]=read();
}
f[0][0]=1;
for(int i=1;i<=n;i++)
{
sum=0;
lst=pow(1-p[i],t[i]-1);
for(int j=1;j<=m;j++)
{
sum*=(1-p[i]);
sum+=f[i-1][j-1]*p[i];
if(j>=t[i])
{
sum-=f[i-1][j-t[i]]*lst*p[i];
f[i][j]+=f[i-1][j-t[i]]*lst;
}
f[i][j]+=sum;
ans+=f[i][j];
}
}
printf("%.9lf\n",ans);
}