美文网首页
Tick or Tick 时钟问题

Tick or Tick 时钟问题

作者: Vincy_ivy | 来源:发表于2019-04-18 12:19 被阅读0次

一个很绕的计算题

hdu~[Tick and Tick]http://acm.hdu.edu.cn/showproblem.php?pid=1006

它的意思就是你输入一个角度D,算出三个时针两两之间的角度都要比D大(最小的D),它们才会happy

我们可以通过计算捋一下逻辑:

秒钟的速度: s=6°/s,分针是1/10°/s,时针是1/120°/s
所以相对速度: s_m=59/10°/s,s_h=719/120°/s,m_h=120/11°/s
所以相差一度所需要的时间: sm=10/59 s/°,sh=120/719 s/°,mh=120/11 s/°
他们差360°的周期为: tsm=3600/59 s,tsh=43200/719 s,tmh=43200/11 s
需要相差的角度为D。
至于周期的处理,我们可以从1s开始到1360012s
rsm>D → Dsm+k1tsm < t < tsm-Dsm+k1tsm;
rsh>D → Dsh+k2tsh < t < tsh-Dsh+k2tsh;
rmh>D → Dmh+k3tmh < t < tmh-Dmh+k3tmh;
k1k2k3是用来循环周期的,刚开始不是很明白为什么是 tsm-D*sm

解释啦.png

三个条件都满足所占的总时间即为时针、分针、秒针相差角度大于n的总时间

#include <iostream>
#include <cstdio>
using namespace std;
int total=12*60*60;
double sm=10/59,sh=120/719,mh=120/11;//相差1°的时间
int main()
{
        int t;
    double D,max,min;

    while(1)
    {
        int happyTicks=0;
        scanf("%lf",&D);
        if(D<0)
            break;
        min=D,max=360-D;
        for(int i=0;i<total;i++)
        {
            if(i<4)
                printf("%lf,%lf,%lf\n",sm*double(i),sh*double(i),mh*double(i));
            if(min<=sm*double(i)&&sm*double(i)<=max&&min<=sh*double(i)&&sh*double(i)<=max&&min<=mh*double(i)&&mh*double(i)<=max)
                happyTicks++;        
        }
        printf("%lf\n",(double)happyTicks/total*100);
    
    }
    return 0;
}   

但是这么做会超时,然后我就放弃了,去找了discuss

  • 秒钟的速度s=6°/s,分针是1/10°/s,时针是1/120°/s *
  • 所以相对速度s_m=59/10°/s,s_h=719/120°/s,m_h=120/11°/s *
  • 所以相差一度所需要的时间sm=10/59 s/°,sh=120/719 s/°,mh=120/11 s/° *
  • 他们差360°的周期为tsm=3600/59 s,tsh=43200/719 s,tmh=43200/11 s *
  • 需要相差的角度为n。 *
  • rsm>n → nsm+k1tsm < t < tsm-nsm+k1tsm; *
  • rsh>n → nsh+k2tsh < t < tsh-nsh+k2tsh; *
  • rmh>n → nmh+k3tmh < t < tmh-nmh+k3tmh; *
  • 三个条件都满足所占的总时间即为时针、分针、秒针相差角度大于n的总时间 *
#include<stdio.h>

void main()
{
    int t;
    double n,sum,ft1,ft2,ft3,et1,et2,et3,max,min;
    double sm,sh,mh,tsm,tsh,tmh,fsm,fsh,fmh,esm,esh,emh;
    sm=10./59.;
    sh=120./719.;
    mh=120./11.;
    tsm=360*sm;
    tsh=360*sh;
    tmh=360*mh;
    while(scanf("%lf",&n))
    {
        if(n<0)
            break;
        sum=0;
        fsm=sm*n;
        fsh=sh*n;
        fmh=mh*n;
        esm=tsm-fsm;
        esh=tsh-fsh;
         emh=tmh-fmh;
//43200究竟是怎么来的,这三层循环之间是怎么扯上关系的?
//43200是因为只算了12小时,12小时所占的比例就相当于24小时所占的比例
//通过两两是否重合来判断          
for(ft3=fmh,et3=emh;et3<=43200;et3+=tmh,ft3+=tmh)   
        {
            for(ft2=fsh,et2=esh;et2<=43200;et2+=tsh,ft2+=tsh)
            {
                if(et2<ft3)              
                    continue;
                if(ft2>et3)
                    break;
                     for(t=0,ft1=fsm,et1=esm;et1<=43200;t=t+1,et1=esm+t*tsm,ft1=fsm+t*tsm)
                     {
                    if(et1<ft3 || et1<ft2)
                        continue;
                    if(ft1>et3 || ft1>et2)
                        break;
                     begin=max(ft1,ft2,ft3)

                    sum+=min-max;
                }
            }
        }
        sum/=432.;                                                // 为什么还有除以432?因为要算概率呀sum/43200*100%
        printf("%.3lfn",sum);                                
    }
}

一个详细的代码

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
// 秒针速度  s = 6°/s  分针速度 m = 1/10° /s 时针 h = 1/120° /s
const double SH = 719.0/120, SM = 59.0/10, MH = 11.0/120;
const double tSH = 43200.0/719, tSM = 3600.0/59, tMH = 43200.0/11;

double Min(double a,double b,double c)
{
    return min(a,min(b,c));
}

double Max(double a,double b,double c)
{
    return max(a,max(b,c));
}

int main()
{
    double D;
    while(cin >> D && D!=-1)
    {
        double bSH,bSM,bMH,eSH,eSM,eMH,Begin,End,Sum = 0;
        bSH = D / SH;
       bSM = D / SM;
        bMH = D / MH;
        //计算第一次满足条件的时间(开始时间)
        eSH = (360-D)/SH;
        eSM = (360-D)/SM;
        eMH = (360-D)/MH;
        //计算第一次不满足条件的时间(结束时间)
        for(double b3 = bSH,e3 = eSH; e3 <= 43200.000001; b3+=tSH,e3+=tSH)
        {
            for(double b2 = bMH,e2 = eMH; e2 <= 43200.000001; b2+=tMH,e2+=tMH)
            {
                if(e2 < b3)         //判断是否有交集    就是要求有交集  
                    continue;      // 判断的话是根据for循环的内外顺序,如果内侧end小于外侧begin还是有机会超过的
                if(b2 > e3)        //三个循环交换顺序都是可以的
                   break;
                for(double b1 = bSM,e1 = eSM; e1 <= 43200.000001; b1+=tSM,e1+=tSM)
                {
                    if(e1 < b2 || e1 < b3)
                        continue;
                    if(b1 > e2 || b1 > e3)
                        break;
                    Begin = Max(b1,b2,b3);  //开始时间取最大,以满足全部要求
                    End = Min(e1,e2,e3);    //结束时间取最小,以满足全部要求
                    Sum += (End-Begin);
                }
            }    
        }
        printf("%.3lf\n",Sum/432);
    }


    return 0;
}

相关文章

  • Tick or Tick 时钟问题

    一个很绕的计算题 hdu~[Tick and Tick]http://acm.hdu.edu.cn/showpro...

  • matplotlib中如何将坐标轴的刻度设置向内或向外

    什么是坐标轴的Tick 坐标轴的tick就是指坐标轴的刻度。Tick的意思有时钟的滴答声,也有钩号的意思。参考下面...

  • 2022-05-03

    fastadmin 打卡 tick 淘宝币 打卡 tick write log 打卡 tick. 背单词...

  • 《Tick Tick Boom》

    其实我一直在思考到底Jon听见的倒数是什么?当然从本人的经历来看,这很有可能是生命时刻的倒数,但在我看来,这更像是...

  • 2022-05-02

    fastadmin 打卡 tick 淘金币 打卡 tick 背英语单词 打卡 tick 今日必做之事: 找...

  • [shared hook]GM/Tick

    原文链接:GM/Tick 函数原型: GM:Tick() 描述: 每一server tick都会被调用, 在服务器...

  • 这样记单词绝对既轻松又难忘

    Time 时间 Fitness健身 Tick 时钟滴答 Records 唱片 Halloween万圣节 Volum...

  • Screeps 中优化 Memory 储存

    问题 在 Screeps 中,Memory 是很重要的存在,它让信息可以在Tick与Tick之间保存状态。但是每个...

  • linux tickGet()

    tickGet()返回的是从系统启动开始tick计数后的总的tick数目。 tick是啥,是“滴答”,它是一个数值...

  • 杭电-1006 Tick and Tick

    这题需要一些耐心,准备好了就来吧。 我们理解题目意思的时候注意,A hand is happy if it is ...

网友评论

      本文标题:Tick or Tick 时钟问题

      本文链接:https://www.haomeiwen.com/subject/msrzwqtx.html