假设一次放k个烟花,为最优的情况,一直放烟花直到出现完美的烟花,该分布为几何分布,设放一次的时间为t,放一个烟花成功的概率为p,期望为t/(1-(1-p)^k),得到期望函数求最小值。
代码:
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<ctime>
using namespace std;
typedef long long ll;
ll t,n,m,pp;
long double p,_p;
long double qpow(long double a,ll b){
long double ans=1.0;
while(b){
if(b&1)ans*=a;
b>>=1;
a=a*a;
}
return ans;
}
long double func(long double k){
return (long double)(n*k+m)/(1-qpow(_p,k));
}
long double func(ll k){
return (long double)(n*k+m)/(1-qpow(_p,k));
}
int main(){
srand(time(NULL));
cin>>t;
while(t--){
cin>>n>>m>>pp;
p=(long double)pp/10000.0;
_p=1.0-p;
long double nowk=1;
long double ans=1e300;
long double ansk;
for(double dx=1e5;dx>=1000;dx*=0.9952){
long double K=nowk;
long double test;
if(K+dx<=1e5){
test=K+dx;
long double temp=func(test);
if(temp<ans) {ans=temp;ansk=test;nowk=test;}
else{
if(rand()%1000<=350) nowk=test;
}
}
if(K-dx>=1) {
test=K-dx;
long double temp=func(test);
if(temp<ans) {ans=temp;ansk=test;nowk=test;}
else{
if(rand()%1000<=350) nowk=test;
}
}
}
for(ll i=ansk-1000;i<=ansk+1000;i++){
if(i<=0) continue;
ans=min(ans,func(i));
}
printf("%.10Lf\n",ans);
}
}