ICPC2020南京 F Fireworks(概率论+三分)

传送门

题目大意:做一个烟花花费n分钟,把做的所有烟花放掉需要m分钟。每次可以选择做烟花,或者把所有的烟花放掉。

每个烟花成功燃放的概率为p*0.0001,一旦有烟花成功燃放就停止。问按最优策略,当有烟花成功燃放时,经过时间期望的最小值。

题解:假设做k次烟花再全部放掉是最优策略。

(为什么不能做5次烟花再全部放掉,再做6次烟花全部放掉时有成功燃放的最优呢?因为这样肯定做6次再全部放掉最优,所以第一轮要改为做6次)

每一轮的时间花费为(k*n+m),每轮有烟花成功燃放的概率为1-(1-p)^k.这是一个几何分布。

它的期望轮数为E=1/(1-(1-p)^k).

所以期望时间为(k*n+m)/(1-(1-p)^k).

三分找一下最小值。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;

#define LL long long
#define DB  double

LL n,m;
DB p;

DB slove(LL k)
{
//    cout<<(DB)((1.*k*n)+m)<<endl;
  //  cout<<(1.-pow(1-p,k))<<endl;
    return ((1.*k*n)+m)/(1.-pow(1-p,k));
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        cin>>n>>m;
         cin>>p;
         p=p*0.0001;
         LL l=1,r=1000000000;
         while(l<r)
         {
         //    cout<<l<<" "<<r<<endl;
             LL midl=l+(r-l)/3;
             LL midr=r-(r-l)/3;
           //  cout<<slove(midl)<<" "<<endl;
             if(slove(midl)>slove(midr)) l=midl+1;
             else r=midr-1;
         }
         printf("%.10lf\n",slove(l));
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章