HDU 1006 Tick and Tick

这道题,开始的时候以一秒为单位做,后来发现过不了。

据说是连续变化的,想了好久,用两根针的相对速度来做。

首先求出时针和分针角度大于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,画出函数图象,求得面积,除以总面积,即得上式。

但是,实际中时针一旦确定,分针和秒针就确定了,它们并不是独立的,所以我想应该是不行的。





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值