输入:
3
1 1 5000
1 1 1
1 2 10000
输出:
4.0000000000
10141.5852891136
3.0000000000
题目大意:有一个人正在制作烟花,这个人制作出一个烟花为“完美烟花”的概率为p/10000,这个人每次制作完烟花后可以有两种选择,一种选择是继续制作烟花,一种选择是花费m分钟,将当前制作出来的还没有燃放的烟花全部点燃,以此来验证这批烟花中是否含有“完美烟花”,他每次制作一个烟花的用时为n分钟,当他发现自己制作出一个"完美烟花"后,他就会去休息,问当他采取最优策略的时候,他至少需要花费多长事件才会去休息。
解题思路:
三分每次制作出k个烟花后选择一次性将其燃放,寻找最优策略,这时有人可能就会问,为什么最优策略是每次选择一样的k个烟花,每次选择的烟花就不会不一样多吗?其实对于这个问题,我们每次选择一次性燃放多少个烟花是相互独立的,那么如果我们上一次选择一次燃放k个烟花是最优策略,那么当前这次同样选择一次燃放k个烟花也一定是最优策略,两个问题的性质是相同的。
现在是给定一个数字x,如何计算一次选择x个烟花燃放的期望事件,公式如下:
前一项表示,我们把制作x个烟花当作一次操作,出现一个“完美烟花”所需要的操作次数
后一项表示一次操作所需要的代价,即x次制作时间n*x加一次点燃时间m
上代码:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cmath>
using namespace std;
int t;
long long n,m;
double p;
long double f(long long x)
{
return (n*x+m)/(1-pow(1-p,x));
}
double eps=1e-4;
int main()
{
cin>>t;
while(t--)
{
cin>>n>>m>>p;
p=p/10000.0;
long long r=100000000,l=1;
long double ans=1e18;
while(r>l)
{
long long mid1=l+(r-l)/3,mid2=l+(r-l)*2/3;
long double f1=f(mid1),f2=f(mid2);
ans=min(ans,min(f1,f2));
if (f1<f2)
r=mid2;
else
l=mid1+1;
}
printf("%.8Lf\n",ans);
}
return 0;
}
/*
1
1 1 1
*/