498B Name That Tune
题目大意
n首音乐,第i首被听出来的概率为pi,刚开始听第一首,1s后如果听出来了则放第下一首,否则接着听这一首,第i首在连续听了ti s之后一定会被听出来,问Ts后听出来的歌的期望数量。
分析
我们非常容易想到dp[i][j]表示考虑前i首歌总共用了j秒的期望得分
但是我们发现转移复杂度O(T),总复杂度O(N^3)
于是我们考虑优化
我们想到对于dp[i][j]的一部分答案可以由dp[i][j-1]*(1-p[i])得到
于是转移复杂度优化到了O(1)
细节较多,详见代码
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
const double eps = 1e-6;
double dp[5050][5050],Ans;
int t[5050],pp[5050];
int main(){
int n,m,i,j,k,T;
scanf("%d%d",&n,&T);
for(i=1;i<=n;i++)scanf("%d%d",&pp[i],&t[i]);
dp[0][0]=1;
for(i=1;i<=n;i++){
double p=(double)pp[i]/100;
double x=pow(1-p,t[i]-1);
double now=dp[i-1][0];
for(j=1;j<=T;j++){
if(j-t[i]>=0)now-=dp[i-1][j-t[i]]*x;
dp[i][j]+=now*p;
if(j-t[i]>=0)dp[i][j]+=dp[i-1][j-t[i]]*x;
now=now*(1-p)+dp[i-1][j];
Ans+=dp[i][j];//我们不将数首歌期望合起来算,而是每次都累加答案
//但是每次算概率是需要用到之前的期望
}
}
printf("%0.6lf",Ans);
return 0;
}