第 45 届国际大学生程序设计竞赛亚洲区域赛(南京)

比赛链接

第 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;
}
posted @ 2022-10-28 22:25  zyy2001  阅读(38)  评论(0编辑  收藏  举报