[UVA][時間計算] 10339 - Watching Watches
Problem D
Watching Watches
Input: standard input
Output: standard output
Time Limit: 10 seconds
Memory Limit: 32 MB
It has been said that a watch that is stopped keeps better time than one that loses 1 second per day. The one that is stopped reads the correct time twice a day while the one that loses 1 second per day is correct only once every 43,200 days. This maxim applies to old fashioned 12-hour analog watches, whose hands move continuously (most digital watches would display nothing at all if stopped).
Given two such analog watches, both synchronized to midnight, that keep time at a constant rate but run slow by k and m seconds per day respectively, what time will the watches show when next they have exactly the same time?
The Input
Input consists of a number of lines, each with two distinct non-negative integers k and m between 0 and 256, indicating the number of seconds per day that each watch loses.
The Output
For each line of input, print k, m, and the time displayed on each watch, rounded to the nearest minute. Valid times range from 01:00 to 12:59
Sample Input
1 2
0 7
Output for Sample Input
1 2 12:00
0 7 10:17
Source: Waterloo ACM Programming Contest
有兩支錶,一個一天慢 k 秒,另一個一天慢 m 秒,慢的方式都是按照平均慢多少秒,也就是慢的話,錶一秒會多於一秒。問多久之後哪個時刻,錶會具有相同的時間。
題目解法:
非常擾人的浮點數誤差,用 double 一直過不了,加 eps 仍然 WA。
最後只好使用不會有誤差的方式。
by Hauser » Sun Aug 18, 2002 3:27 pm
Let x be the difference between the two watches after one day (in seconds)
x = |a-b|
So the difference between two watches after one second (y) will be
y = x / 86400
Both watches will show the same time after the difference between
their times will be 12h, that is 43200 seconds, so
t = 43200 / y
Where t is the real time after which watches will be synchronized.
First watch goes (86400-a)/86400 times slower than "real time clocks".
So it will show:
seconds = t * (86400-a)/86400 = ( (86400-a)*43200 ) / |a-b|
minutes = ( (86400-a)*43200 ) / ( 60*|a-b| )
'minutes' looks like that m/n, what we have to do is to divide
'm' by 'n' treating them as integers (result will be floor-ed ),
and then check out if we have to add one to round result good
if( (m%n)*2 >= n )
minutes++;
And we have our result. It's simply, isn't it?
![;)](http://acm.uva.es/board/images/smilies/icon_wink.gif)
(Use long longs, otherwise integer overflow guaranteed.)
Hauser
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main() {
int k, m;
while(scanf("%d %d", &k, &m) == 2) {
if(k == m) {
printf("%d %d 12:00\n", k, m);
continue;
}
long long a, b;
long long minutes = (86400LL - k)*43200 / (60*abs(k-m));
a = (86400LL-k)*43200, b = 60LL*abs(k-m);
if((a%b)*2 >= b) minutes++;
long long hh = (minutes/60)%12, mm = minutes%60;
if(hh == 0) hh = 12;
printf("%d %d %02lld:%02lld\n", k, m, hh, mm);
}
return 0;
}