传送门: https://ac.nowcoder.com/acm/contest/10272/F
题意
n分钟做一个烟花,m分钟放掉所有做完的烟花。p的概率制造出完美的烟花。问最少的期望时间可以做出完美的烟花。
思路
这个烟花只有是不是完美的两种,所以是几何分布。而几何分布的期望为 1 p \frac{1}{p} p1,所以我们需要知道一次性做多少个烟花可以做出完美的烟花。
假设我们制造出k个烟花,然后一次性花m分钟释放完,其中就有完美的烟花,所以我们的总时间为 ( n ∗ k + m ) (n*k+m) (n∗k+m),而存在完美烟花的概率为 1 − ( 1 − p ) k 1-(1-p)^k 1−(1−p)k,所以做出一个完美烟花的期望为 1 1 − ( 1 − p ) k \frac{1}{1-(1-p)^k} 1−(1−p)k1,乘上时间,总期望时间为 ( n ∗ k + m ) 1 − ( 1 − p ) k \frac{(n*k+m)}{1-(1-p)^k} 1−(1−p)k(n∗k+m)。
所以我们想知道这个k是多少。回答:三分答案。
因
为
总
期
望
时
间
函
数
不
是
单
调
的
,
所
以
二
分
不
行
的
,
需
要
三
分
。
因为总期望时间函数不是单调的,所以二分不行的,需要三分。
因为总期望时间函数不是单调的,所以二分不行的,需要三分。
即
三
分
答
案
,
枚
举
k
,
刚
开
始
的
区
间
为
[
1
,
10000
]
。
取
最
小
a
n
s
即
可
。
即三分答案,枚举k,刚开始的区间为[1,10000]。取最小ans即可。
即三分答案,枚举k,刚开始的区间为[1,10000]。取最小ans即可。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pdd;
#define INF 0x3f3f3f3f
#define lowbit(x) x & (-x)
#define mem(a, b) memset(a , b , sizeof(a))
#define FOR(i, x, n) for(int i = x;i <= n; i++)
// const ll mod = 998244353;
// const ll mod = 1e9 + 7;
// const double eps = 1e-6;
// const double PI = acos(-1);
// const double R = 0.57721566490153286060651209;
ll n, m;
double p;
double quick_pow(double a, int b) {
double ans = 1;
while(b) {
if(b & 1) ans = ans * a;
a = a * a;
b >>= 1;
}
return ans;
}
double Clac(int k) {
return (k * n + m) / (1 - quick_pow(1 - p, k));
}
void solve() {
int _; scanf("%d",&_);
while(_--) {
scanf("%lld%lld%lf",&n,&m,&p);
p *= 0.0001;
int l = 1, r = 100000;
double ans = (n + m) / p;
while(r - l >= 10) {
int mid1 = l + (r - l) / 3;
int mid2 = r - (r - l) / 3;
if(Clac(mid1) < Clac(mid2)) r = mid2;
else l = mid1;
}
for(int i = l;i <= r; i++) {
ans = min(ans, Clac(i));
}
printf("%lf\n",ans);
}
}
signed main() {
solve();
}