这道题,开始的时候以一秒为单位做,后来发现过不了。
据说是连续变化的,想了好久,用两根针的相对速度来做。
首先求出时针和分针角度大于D的一个区间,
然后在这个区间下,求分针和秒针角度大于D的区间,
最后在这个区间下,求时针和秒针角度大于D的区间长度。
这样,就有三个循环。
#include<stdio.h>
double d;
double h_m=11/120.0,m_s=5.9,h_s=5+119/120.0;//相对速度
double aT=360/h_m, bT=360/m_s,cT=360/h_s;//周期
double ahappy,bhappy,chappy,happy; //两两符合的时间
int main()
{
double alow,blow,bhigh,clow,chigh,l,h,temp;
while(scanf("%lf",&d),d!=-1)
{
happy=0;
ahappy=(360-2*d)/h_m;
bhappy=(360-2*d)/m_s;
chappy=(360-2*d)/h_s;
for(alow=d/h_m;alow<12*3600;alow+=aT)
{
blow=alow,bhigh=alow+ahappy;
clow=bT*(int)(blow/bT)+d/m_s;
while(clow<blow && clow+bhappy<=blow) clow+=bT;
for(;blow<bhigh;)
{
chigh=clow+bhappy;
if(clow>=bhigh)
break;
if(clow<blow)//边界修正
clow=blow;
if(chigh>bhigh)//边界修正
chigh=bhigh;
l=cT*(int)(clow/cT)+d/h_s;
while(l<clow && l+chappy<=clow) l+=cT;
for(;clow<chigh;)
{
temp=l;
h=l+chappy;
if(l>=chigh)
break;
if(l<clow)
l=clow;
if(h>chigh)
h=chigh;
happy+=h-l;
l=clow=temp+cT;
}
clow=blow=chigh+2*d/m_s;
}
}
printf("%.3lf\n",happy/432);
}
return 0;
最坏情况下,最内层循环大概有800多次。
在HDU OJ用时15ms,不知道什么方法能做的0ms.
还有人用概率做,结果不错,和答案很接近。
#include<stdio.h>
int main(){
int D;
double percentage;
while(scanf("%d",&D)&&D!=-1){
percentage = 100*(1-D/120.0)*(1-D/120.0);
printf("%.3lf\n",percentage);
}
}
仅凭这个公式,我没想出原理,后来看到
((360 - 3*n)/360)^2 = (120 - n)^2/14400
这种方法假设三根针等概率落在[0,360]上,
首先第一根针落下,把这个位置记为0,然后第二根和第三根只能落在[D,360-D],因为这样和第一根针夹角才能保证大于等于D,
同时,第二根和第三根应该满足|x-y|>D,画出函数图象,求得面积,除以总面积,即得上式。
但是,实际中时针一旦确定,分针和秒针就确定了,它们并不是独立的,所以我想应该是不行的。