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; }

猜你喜欢

转载自www.cnblogs.com/yzxverygood/p/10360444.html