算法分析
秒针(S): 1s 360/60= 6 度(degree)
分针(M): 1s 360/60*60= 1/10度(degree)
时针(H): 1s 360/60*60*12= 1/120度(degree)
秒针与分针的相对速度为:
V(M,S) = 6-1/10 = 59/10 d/s;
同理, 时针与秒针 V(H,S) = 6-1/120 =719/120 d/s;
V(H,M) = 1/10-1/120 = 11/120 d/s.
秒针与分针的相遇周期为
T(M,S)= 360/V(M,S)= 3600/59;
同理, T(H,S)= 360/V(H,S)=43200/719;
T(H,M)= 360/V(H,M)=43200/11;
在一天24小时内,后12个小时与前12个小时情况完全相同,故只取12个小时即可。
则12个小时总秒数
T = 12h * 60m* 60s = 43200s
秒针与分针的相遇次数为
N(M,S)=T/T(M,S) = 59*12 = 708
同理, N(H,S)=T/T(H,S) = 719
N(H,M)=T/T(H,M) = 11
由于周期性规律可知:
假设秒针与分针之间的角度用函数F(t)表示,则 F(t)为某一时刻t两针之间的角度。
F(t+n*T(M,S)) = F(t) , 其中n为自然数,
同理, F(t+n*T(H,S)) = F(t)
F(t+n*T(H,M)) = F(t)
所以,我们只要计算出第一个周期内的各指针之间的幸福时间区段,再加上若干个各自周期后,仍为幸福区段。
假设角度差至少为D时,秒针和分针才幸福,则在第一个周期T(M,S)内,
D<= V(M,S)*t <= 360-D
解得 t1=D/V(M,S)
t2=(360-D)/V(M,S);
根据周期性,
happy(t ms) =(t1+n*T(M,S),t2+n*T(M,S)) 0 <= n < N(M,S);
同理, happy(t hs ) =(t1+n*T(H,S),t2+n*T(H,S)) 0 <= n < N(H,S);
happy(t hm) =(t1+n*T(H,M),t2+n*T(H,M)) 0 <= n < N(H,M);
最后,求得三者的交集区间长度
L = happy(t ms) X happy(t hs) X happy(t hm) ,(X表示关系交)即可。
#include <iostream> #include <iomanip> using namespace std; const int T = 360*120, NMS = 708,NHM = 11, NHS = 719; //相遇次数 const double F = 0.0466631; //F为调节系数,使得各区间段为准确值 const double hmlen = T*F/NHM,mslen = T*F/NMS,hslen = T*F/NHS; struct interval { double low,high; }; interval andset(interval S1,interval S2) { interval zone; zone.low = S1.low > S2.low ? S1.low : S2.low; zone.high = S1.high < S2.high ? S1.high : S2.high; if( zone.low >= zone.high ) zone.low = zone.high = 0.0; return zone; } int main() { int D=0; while(cin>>D&&D!=-1) { double len = 0.0; interval ms,hs,hm; hm.low = hmlen*D/360 - hmlen; hm.high = - hm.low -hmlen; ms.low = mslen*D/360 - mslen; ms.high = - ms.low -mslen; hs.low = hslen*D/360 - hslen; hs.high = - hs.low -hslen; for(int i=0,j=0,k=0;i<NHM;i++) { hm.low+=hmlen; hm.high+=hmlen; for(;j<NMS;j++) { ms.low+=mslen; ms.high+=mslen; interval temp1 = andset(hm,ms); if(temp1.low!=0||temp1.high!=0) { for(;k<NHS;k++) { hs.low+=hslen; hs.high+=hslen; interval temp2 = andset(temp1,hs); len+=temp2.high-temp2.low; if(hs.high>=temp1.high) { hs.low-=hslen; hs.high-=hslen; break; } } } if(ms.high>=hm.high) { ms.low-=mslen; ms.high-=mslen; break; } } } cout<<setprecision(3)<<fixed<<len/(432*F)<<endl; } return 0; }