您的位置:首页 > 其它

Codeforces Round #364 (Div. 2) D. As Fast As Possible __ binary search、方程 或解方程 直接解出答案

2016-09-25 22:56 344 查看
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 k people (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 n, l, v1, v2 and k (1 ≤ n ≤ 10 000, 1 ≤ l ≤ 109, 1 ≤ v1 < v2 ≤ 109, 1 ≤ 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.

Source

Codeforces Round #364 (Div. 2)

My Solution

binary search、方程

1、binary search、方程

每个pupil 坐车的时间相同、走路的时间相同、总时间相同。

所以 l = 0, r = INF;

对于 每个答案 x,验证总时间 cnt <= x,即车跑的总时间要小于等于 总的总时间

t1 + t2 == x            // t1 为每个pupil 走路的总时间, t2 为每个pupil坐车的总时间,每个pupil 都必须且只做一次车

v1 * t1 + v2 * t2 == l(路程)    //求出 t2

-------------------------------->

                <----------------

                -------------------------------->

                                <----------------    

                                -------------------------------->

                          ......               ......

                                                                   -------------------------------->

           

就像图中所示每次 -->的时间都是 t2, 每次 <--的时间都是 dt,

(t2 + dt) * v1 == t2 * v2 - dt * v2;        //求出 dt     

求出车子跑的总时间 cnt = t2 + (t - 1) *(dt + t2)         //其中 t表示车子载人的总次数, t = n / k, 当 t * k < n 时 t++

这样 cnt <= x 则 时间还可以更短 r = x, 否则时间不够 l = x;

此外 eps = 1e-6的时候Accepted了,最开始 eps取了1e-12导致一些特殊数据时无法跳出while循环 而TLE,如果直接解方程就基本上误差非常小了(请看方法2)

复杂度 O(logn)

2、解方程 直接解出答案

其实有以上的这些方程组可知,最后可以化成关于 x 的一次不等式

t1 + t2 == x  

t = n / k, 当 t * k < n 时 t++

v1 * t1 + v2 * t2 == l(路程)    //求出 t2

(t2 + dt) * v1 == t2 * v2 - dt * v2

cnt = t2 + (t - 1) *(dt + t2)

cnt <= x

当 cnt 无限趋向于 x时, 求出的x就是答案, 而且精确度比二分法高的多。

ans = (s + ((t - 1) * ((v2  - v1) / (v1 + v2) + 1))*s) / (v2 + ((t - 1) * ((v2  - v1) / (v1 + v2) + 1)) * v1);

复杂度 O(1)

1、Source code for binary search、方程

#include <iostream>
#include <cstdio>
#include <iomanip>
using namespace std;
typedef long long LL;
const int maxn = 1e6 + 8;
const int INF = 1e9 + 7;
const double eps = 1e-6;

int n, k, t;
double s, v1, v2, t1, t2, cnt;
//t1 + t2 == x; v1*t1 + v2*t2 == s
inline bool check(double x)
{
t2 = (s - x * v1) / (v2 - v1);
//then check whether this t2 is possible.
cnt = t2;
//for(int i = 2; i <= t; i++){
cnt += (t - 1)*((v2 * t2 - v1 * t2) / (v1 + v2) + t2);
//}
if(cnt > x) return false;
else return true;

}

int main()
{
#ifdef LOCAL
freopen("d.txt", "r", stdin);
//freopen("d.out", "w", stdout);
int T = 3;
while(T--){
#endif // LOCAL
ios::sync_with_stdio(false); cin.tie(0);

cin >> n >> s >> v1 >> v2 >> k;
t = n / k;
if(t * k < n) t++;
double l = 0, r = INF, x;
while(l + eps < r){
x = (l + r) / 2;
if(check(x)) r = x;
else l = x;
//cout << l << " " << r << endl;
}
cout << fixed << setprecision(10) << min(x, s / v1) << endl;

#ifdef LOCAL
cout << endl;
}
#endif // LOCAL
return 0;
}


2、Source code for 解方程 直接解出答案

#include <iostream>
#include <cstdio>
#include <iomanip>
using namespace std;
typedef long long LL;
const int maxn = 1e6 + 8;
const int INF = 1e9 + 7;
const double eps = 1e-6;

int n, k, t;
double s, v1, v2, t1, t2, cnt;
//t1 + t2 == x; v1*t1 + v2*t2 == s
/*
inline bool check(double x)
{
t2 = (s - x * v1) / (v2 - v1);
//then check whether this t2 is possible.
cnt = t2;
//for(int i = 2; i <= t; i++){
cnt += (t - 1)*((v2 * t2 - v1 * t2) / (v1 + v2) + t2);
//}
if(cnt > x) return false;
else return true;

}
*/

int main()
{
#ifdef LOCAL
freopen("d.txt", "r", stdin);
//freopen("d.out", "w", stdout);
int T = 3;
while(T--){
#endif // LOCAL
ios::sync_with_stdio(false); cin.tie(0);

cin >> n >> s >> v1 >> v2 >> k;
t = n / k;
if(t * k < n) t++;
/*
double l = 0, r = INF, x;
while(l + eps < r){
x = (l + r) / 2;
if(check(x)) r = x;
else l = x;
//cout << l << " " << r << endl;
}
*/
double k = (t - 1) * ((v2  - v1) / (v1 + v2) + 1);
double ans = (s + k*s) / (v2 + k * v1);
cout << fixed << setprecision(10) << min(ans, s / v1) << endl;

#ifdef LOCAL
cout << endl;
}
#endif // LOCAL
return 0;
}


  Thank you!

                                                                                                           
                                   ------from ProLights 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: