【Codeforces Round 364 (Div 2)D】【二分答案 or 公式推导】As Fast As Possible 小朋友乘校车去远足最短到达时间

D As Fast As Possible
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

On vacations n pupils decided to go on excursion and gather all together. They need to overcome the path with the length l meters. Each of the pupils will go with the speed equal to v1. To get to the excursion quickly, it was decided to rent a bus, which has seats for kpeople (it means that it can't fit more than k people at the same time) and the speed equal to v2. In order to avoid seasick, each of the pupils want to get into the bus no more than once.

Determine the minimum time required for all n pupils to reach the place of excursion. Consider that the embarkation and disembarkation of passengers, as well as the reversal of the bus, take place immediately and this time can be neglected.

Input

The first line of the input contains five positive integers nlv1v2 and k (1 ≤ n ≤ 10 0001 ≤ l ≤ 1091 ≤ v1 < v2 ≤ 1091 ≤ k ≤ n) — the number of pupils, the distance from meeting to the place of excursion, the speed of each pupil, the speed of bus and the number of seats in the bus.

Output

Print the real number — the minimum time in which all pupils can reach the place of excursion. Your answer will be considered correct if its absolute or relative error won't exceed 10 - 6.

Examples
input
5 10 1 2 5
output
5.0000000000
input
3 6 1 2 1
output
4.7142857143
Note

In the first sample we should immediately put all five pupils to the bus. The speed of the bus equals 2 and the distance is equal to 10, so the pupils will reach the place of excursion in time 10 / 2 = 5.


#include<stdio.h>
#include<iostream>
#include<string.h>
#include<string>
#include<ctype.h>
#include<math.h>
#include<set>
#include<map>
#include<vector>
#include<queue>
#include<bitset>
#include<algorithm>
#include<time.h>
using namespace std;
void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); }
#define MS(x,y) memset(x,y,sizeof(x))
#define MC(x,y) memcpy(x,y,sizeof(x))
#define MP(x,y) make_pair(x,y)
#define ls o<<1
#define rs o<<1|1
typedef long long LL;
typedef unsigned long long UL;
typedef unsigned int UI;
template <class T1, class T2>inline void gmax(T1 &a, T2 b) { if (b>a)a = b; }
template <class T1, class T2>inline void gmin(T1 &a, T2 b) { if (b<a)a = b; }
const int N = 0, M = 0, Z = 1e9 + 7, ms63 = 0x3f3f3f3f;
int n, k;
double dis, v1, v2;
bool check(double limit)
{
	int top = n / k + (n%k > 0);	//要运送小朋友多少波
	double nowt = 0;				//步行大军现在的时间
	double nowd = 0;				//步行大军现在的位置
	for (int i = 1; i <= top; ++i)	//处理每波小朋友
	{
		double dd = dis - nowd;		//小朋友还要走的距离
		double tt = limit - nowt;	//截止时间剩下的时间
		double go = tt*v1;			//如果纯步行能走多远
		if (go >= dd)return 1;		//纯步行就OK啦
		double more = dd - go;		//走不到的距离要换车
		double dri = more / (v2-v1);//至少需要乘车的时间
		nowt += dri;				//步行大军之后的时间
		nowd += dri*v1;				//步行大军之后的位置
		if (i < top)				//车要返程,求相遇状态
		{
			double d = dri*(v2 - v1);
			double t = d / (v2 + v1);
			nowt += t;
			nowd += t*v1;
		}
		if (nowt > limit)return 0;
	}
	return 1;
}
void O1()
{
	double x = n / k + (n%k > 0);
	double y = (x - 1) * (v2 - v1) / (v1 + v2);
	double t2 = dis / v2 / (x - y);
	double t1 = (dis - t2 * v2) / v1;
	printf("%.10f\n", t1 + t2);
}
int main()
{
	while (~scanf("%d%lf%lf%lf%d", &n, &dis, &v1, &v2, &k))
	{
		O1(); continue;
		double l = dis / v2;
		double r = dis / v1;
		for (int tim = 1; tim <= 200; ++tim)
		{
			double mid = (l + r) / 2;
			check(mid) ? r = mid : l = mid;
		}
		printf("%.10f\n", l);
	}
	return 0;
}
/*
【题意】
有n个小朋友要到达dis距离的目的地。
小朋友的速度为v1
校车的速度为v2(v1<v2)
每个小朋友最多乘车一次
车每次最多可以载k个小朋友。
车可以往返运动。
问你,所有小朋友都到达目的地的最早时间是什么。

【类型】
二分答案 or 公式推导

【分析】
这题,显然我们可以二分答案并验证可行性。
假设我们知道最晚抵达时间了。就知道我们要每个小朋友要最少乘车多久了。
配合模拟即可AC。


不过我们还有另外一种O(1)的公式算法——
这种算法首先要基于一定的贪心原则:
我们设一共有g组小朋友,共乘车g次(显然g=(n/k)+(n%k>0))
那么——
1,每个(组)人乘车的时间是相同的(设为t2),步行时间也是相同的(设为t1)
2,所有人和车最后同时到达终点
3,车一共做了g次向前运行的时间,g-1次返程的时间。

我们可以列出以下几组方程:
1,每个人的位移公式——
	(t1*v1)+(t2*v2)==dis,已知t1、t2中的一者,就可以直接求出另外一者。

2,每组人乘车,会使得其与下组人的距离差增加t2*(v2-v1),
	车在返程中所会用去的时间为——t2*(v2-v1)/(v1+v2)

3,显然,(车向前开的时间 - 车向后开的时间)*车速=总位移
	g*t2 - (g-1)*(t2*(v2-v1)/(v1+v2)) == dis/v2 

这样我们就可以快速算出t2和t1,并求解出答案啦。

【时间复杂度&&优化】
O(log * n) or O(1)

*/


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值