前言
我姐姐买狗时被骗1200元,还签了支付宝合同,每月自动扣款300元,缴12个月。家人不报警,在评论区求解决,谢谢!
题目描述
蛋蛋非常热衷于挑战自我,今年暑假他准备沿川藏线骑着自行车从成都前往拉萨。
川藏线的沿途有着非常美丽的风景,但在这一路上也有着很多的艰难险阻,路况变化多端,而蛋蛋的体力十分有限,因此在每天的骑行前设定好目的地,同时合理分配好自己的体力是一件非常重要的事情。
由于蛋蛋装备了一辆非常好的自行车,因此在骑行过程中可以认为他仅在克服风阻做功(不受自行车本身摩擦力以及自行车与地面的摩擦力影响)。
某一天他打算骑 n 段路,每一段内的路况可视为相同:对于第 i 段路,我们给出有关这段路况的 33 个参数 ′si,ki,vi′,其中 si 表示这段路的长度,ki 表示这段路的风阻系数,′vi′ 表示这段路上的风速(′vi′>0 表示在这段路上他遇到了顺风,反之则意味着他将受逆风影响)。
若某一时刻在这段路上骑车速度为 v,则他受到的风阻 大小为 2F=ki(v−vi′)2(这样若在长度为 s 的路程内保持骑行速度 v 不变,则他消耗能量(做功)E=ki(v−vi′)2s )。
设蛋蛋在这天开始时的体能值是 EU,请帮助他设计一种行车方案,使他在有限的体力内用最短的时间到达目的地。请告诉他最短的时间 T 是多少。
输入格式
第一行包含一个正整数 n 和一个实数 EU,分别表示路段的数量以及蛋蛋的体能值。
接下来 n 行分别描述 n 个路段,每行有 33 个实数 ′si,ki,vi′ 分别表示第 �i 段路的长度,风阻系数以及风速。
输出格式
输出一个实数 T,表示蛋蛋到达目的地消耗的最短时间,要求至少保留到小数点后 66 位。
输入输出样例
输入 #1复制
3 10000 10000 10 5 20000 15 8 50000 5 6
输出 #1复制
12531.34496464
说明/提示
样例说明
一种可能的方案是:蛋蛋在三段路上都采用匀速骑行的方式,其速度依次为 5.12939919,8.03515481,6.178379675.12939919,8.03515481,6.17837967。
评分方法
本题没有部分分,你程序的输出只有和标准答案的差距不超过 10−610−6 时,才能获得该测试点的满分,否则不得分。
数据规模与约定
对于 10%10% 的数据,n=1。
对于 40%40% 的数据,n≤2。
对于 60%60% 的数据,n≤100。
对于 80%80% 的数据,n≤1000。
对于 100%100% 的数据,n≤104,EU≤108,si∈[0,105],ki∈(0,15],vi′∈(−100,100)。
数据保证最终的答案不会超过 105105。
提示
必然存在一种最优的体力方案满足:蛋蛋在每段路上都采用匀速骑行的方式。
题解
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#define enter putchar('\n')
#define space putchar(' ')
using namespace std;
typedef long long ll;
template <class T>
void read(T &x){
char c;
bool op = 0;
while(c = getchar(), c < '0' || c > '9')
if(c == '-') op = 1;
x = c - '0';
while(c = getchar(), c >= '0' && c <= '9')
x = x * 10 + c - '0';
if(op == 1) x = -x;
}
template <class T>
void write(T x){
if(x < 0) putchar('-'), x = -x;
if(x >= 10) write(x / 10);
putchar('0' + x % 10);
}
const int N = 10005, INF = 0x3f3f3f3f;
int n;
double E, s[N], k[N], u[N];
double getv(double x, int i){
double l = max(u[i], double(0)), r = 100005, mid;
int cnt = 60;
while(cnt--){
mid = (l + r) / 2;
if(2 * k[i] * x * mid * mid * (mid - u[i]) > -s[i]) l = mid;
else r = mid;
}
mid = (l + r) / 2;
return (l + r) / 2;
}
double calc(double x){
double sum = 0;
for(int i = 1; i <= n; i++){
double v = getv(x, i);
sum += k[i] * (v - u[i]) * (v - u[i]);
}
return sum;
}
int main(){
scanf("%d%lf", &n, &E);
for(int i = 1; i <= n; i++)
scanf("%lf%lf%lf", &s[i], &k[i], &u[i]), k[i] *= s[i];
double l = -INF, r = 0, mid;
int cnt = 100;
while(cnt--){
mid = (l + r) / 2;
if(calc(mid) <= E) l = mid;
else r = mid;
}
mid = (l + r) / 2;
double ans = 0;
for(int i = 1; i <= n; i++)
ans += s[i] / getv(mid, i);
printf("%.10lf\n", ans);
return 0;
}