比赛链接
第 45 届国际大学生程序设计竞赛亚洲区域赛(南京)
F.Fireworks
制作一个烟花需要n分钟,成功的概率为p。完成一次制作后可以继续制作或花m分钟点燃之前所有的烟花,如果有一个烟花是成功的,那么就可以开始休息。
求最小的期望开始休息时间(即期望的最早成功制作一个烟花的时间)
解题思路
三分,期望
题目转化为每轮制作烟花 \(k\) 次,释放一次的最小期望,记期望代价为 \(f(k)\),每轮代价为 \(k\times n+m\),设 \(q=1-p\),即失败的概率,则其前 \(k\) 次中成功的概率为 \(1-q^k\),此分布为几何分布,期望为 \(\frac{1}{1-q^k}\),则其期望代价为 \(\frac{k\times n+m}{1-q^k}\),此函数为单峰函数,三分求极值即可
- 时间复杂度:\(O(logn)\)
代码
// Problem: Fireworks
// Contest: NowCoder
// URL: https://ac.nowcoder.com/acm/contest/45201/F
// Memory Limit: 524288 MB
// Time Limit: 4000 ms
//
// Powered by CP Editor (https://cpeditor.org)
// %%%Skyqwq
#include <bits/stdc++.h>
//#define int long long
#define help {cin.tie(NULL); cout.tie(NULL);}
#define pb push_back
#define fi first
#define se second
#define mkp make_pair
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef pair<LL, LL> PLL;
template <typename T> bool chkMax(T &x, T y) { return (y > x) ? x = y, 1 : 0; }
template <typename T> bool chkMin(T &x, T y) { return (y < x) ? x = y, 1 : 0; }
template <typename T> void inline read(T &x) {
int f = 1; x = 0; char s = getchar();
while (s < '0' || s > '9') { if (s == '-') f = -1; s = getchar(); }
while (s <= '9' && s >= '0') x = x * 10 + (s ^ 48), s = getchar();
x *= f;
}
int t,n,m;
double p,q;
double f(double k)
{
return (1.0*k*n+m)/(1.0-pow(q,k));
}
int main()
{
for(cin>>t;t;t--)
{
cin>>n>>m>>p;
p*=0.0001,q=1-p;
int l=0,r=1e9;
double res=1e18;
while(l<r)
{
int midl=l+(r-l)/3,midr=r-(r-l)/3;
double fl=f(midl),fr=f(midr);
if(fl<=fr)r=midr-1;
else
l=midl+1;
res=min({res,fl,fr});
}
printf("%.10lf\n",res);
}
return 0;
}
标签:竞赛,期望,int,double,45,long,烟花,程序设计,define
From: https://www.cnblogs.com/zyyun/p/16837716.html