时分秒针重合---问题
网络搜索引擎的答案:
问题
在一天的24小时之中,时钟的时针、分针和秒针完全重合在一起的时候有几次?都分别是什么时间?你怎样算出来的?
分析
初看此问题觉得很简单,但是网上各种版本的答案都各不相同,那到底谁是对的呢?
我们可以这样考虑——龟兔赛跑,跑得慢的针终归会被快的一圈一圈超过。那么,分别求出时针分针、分针秒针的重合时间,然后再看是否有相同。
这里都不难,关键是有一个陷阱!请问大家,我说“一圈一圈超过”,是不是每圈都被超过?
先求角速度:(度/秒)
1. 时针:w1 = 360 / 12*3600 = 1/120 d/s
2. 分针:w2= 360 / 3600 = 0.1 d/s
3. 秒针:w3 = 360 / 60 = 6 d/s
设3个针当中,快针角速度为wf,慢针角速度为ws。若快针在一天24小时中,转k = 0, 1, 2, 3, … , n圈的时候,重合慢针的时间为t,则:
wf * t - k*360 = ws*t – [ws/wf * k] *360
t = 360*( k - [k*ws/wf] ) / (wf - ws)
代码如下:
List<double> Times_Overlap(double wf, double ws)
{
var n = (int)(24 * 3600 * wf / 360);
var times = new List<double>(n);
for (int k = 0; k < n - 1; k++)
{
var t = 360 * (k - (int)(k * ws / wf)) / (wf - ws);
//t = Math.Round(t);
if (times.Count == 0 || times[times.Count - 1] != t) times.Add(t);
}
return times;
}
运行程序可以得到(显示出來的时间按秒取整了):
时针分针重合的时间 Times_Overlap(w2, w1):
(1) 00:00:00, (2) 01:05:27, (3) 02:10:54, (4) 03:16:21, (5) 04:21:49, (6) 05:27:16, (7) 06:32:43, (8) 07:38:10, (9) 08:43:38, (10) 09:49:05, (11) 10:54:32, (12) 12:00:00, (13) 13:05:27, (14) 14:10:54, (15) 15:16:21, (16) 16:21:49, (17) 17:27:16, (18) 18:32:43, (19) 19:38:10, (20) 20:43:38, (21) 21:49:05, (22) 22:54:32,
分针秒针重合的时间 Times_Overlap(w3, w2):
(1) 00:00:00, (2) 00:01:01, (3) 00:02:02, (4) 00:03:03, (5) 00:04:04, (6) 00:05:05, (7) 00:06:06, (8) 00:07:07, (9) 00:08:08, (10) 00:09:09, (11) 00:10:10, (12) 00:11:11, (13) 00:12:12, …… 23:53:53, (1412) 23:54:54, (1413) 23:55:55, (1414) 23:56:56, (1415) 23:57:57, (1416) 23:58:58,
时分秒针重合的时间:
00:00:00 12:00:00
讨论
通过Times_Overlap(w2, w1) 算出所有时针和分针重合时间;通过Times_Overlap(w3, w2)算出所有分针和秒针重合时间,可以得到总共重合2次:0点和12点。
需要注意的是,快针和慢针每在0点重合,下一圈快针和慢针将不会相遇。因此,时针和分针相遇22次,时针和秒针相遇1438次,分针和秒针相遇1416次
对整个问题的分析是很不错的,只是红字部分:wf * t - k*360 = ws*t – [ws/wf * k] *360有错误
应该为wf * t - k*360 = ws*t(也就是等式左边快针在t时间走过的角度减去慢针走过的角度是360的整数倍) 。
对此可以简单的举个例子假设即可得出错误:对于(2) 01:05:27这个时间来说,k=1,原来的式子的出来的结果是3600秒
而不是事实的3927秒;
测试代码(devC++)如下:
1 #include<iostream> 2 #include<list> 3 using namespace std; 4 typedef list<double> LIST; 5 int Times_Overlap(double wf, double ws) 6 { 7 int n = (int)(24 * 3600 * wf / 360); 8 LIST times(n); 9 for (int k = 0; k < n - 1; k++) 10 { 11 //double t = 360 * (k - (k * ws / wf)) / (wf - ws); 12 double t = 360*k / (wf - ws); 13 if (times.size() == 0 || t<3600*24) 14 times.push_back(t); 15 } 16 LIST::iterator it = times.begin(); 17 for(;it!=times.end();it++) 18 { 19 cout<<*it<<"\t"; 20 } 21 } 22 int main() 23 { 24 double wf =0.1; 25 double ws=(double)1/(double)120; 26 Times_Overlap(wf,ws); 27 system("pause"); 28 }