【问题描述】
作为出题人的小Z相信大家对上图这样的圆盘时钟都不会陌生——在理想圆盘时钟上,秒针每一分钟转一圈,分针每一小时转一圈,时针每12小时转一圈,它们均是匀速转动的,在0点时三条针均指向表盘上的12。
考虑圆盘时钟与电子时钟之间的转换,显然,对于任意一个形如 hh:mm:ss的电子时钟式的时间(其中0 <=hh<=11,0<=mm,ss<=59),我们均可以很容易地确定时针分针秒针在理想的圆盘时钟上的位置,并计算出三条针两两之间的夹角(要求均不大于180°)。
小Z以前在Codeforces上看到一种构造题目的方法——把题目反转,于是他想到这么一个问题:如果给定三条针两两之间的夹角,那么是否可以确定当前的时刻,或者判断出有多个时刻符合条件,或者判断出不存在符合条件的时刻?
但是小Z实在太菜了,于是这个问题就被交给你来解决了。
【输入格式】
第一行为一个正整数T,表示数据组数。
接下来T组数据,每组数据一行三个用空格隔开的,形如a/b的最简分数(如果是整数,则b=1),分别表示时针与分针、时针与秒针、分针与秒针之间的夹角的度数。
【输出格式】
每组数据第一行输出一个非负整数n,表示符合条件的时刻个数,接下来n行,按照hh:mm:ss的格式(其中0<=hh<=11,0<=mm,ss<=59)从早到晚输出所有符合条件的时刻。
【样例输入】
5
0/1 0/1 0/1
90/1 90/1 0/1
60/1 60/1 60/1
55/2 5/2 30/1
45/1 135/1 180/1
【样例输出】
1
00:00:00
2
03:00:00
09:00:00
0
2
00:05:00
11:55:00
2
04:30:00
07:30:00
【数据规模与约定】
对于30%的数据,保证答案如果存在,那么mm=ss=0。
对于60%的数据,保证答案如果存在,那么ss=0。
对于100%的数据,1<=T<=500,分数a/b是既约分数,且满足0<=a<=43200,1<=b<=43200,且0<=a/b<=180。
题目分析
我们先分析一下题意:知道夹角求的是时间,我们可以枚举时间然后打表,此举不保证你会爆炸,但保证你会写的很不爽。我们分析一下假设是i时j分k秒,就得到如下关系:
时分 :30(i+j/60+k/3600)-6(j+k/60)=30i-5.5j-11/120k=(x||180-x)
时秒:30(i+j/60+k/3600)-6k=30i-0.5j-719/120k=(y||180-y)
分秒:6(j+k/60)-6k=6j-59/60k=(z||180-z)
这里有点坑啊,一个角度可能是两种情况,组合一下就有8种情况了。我们输入的时候用string分开各个比值,解一下三元一次方程组即可,解线性方程组用高斯消元就可以了。
代码实现
原来我写不出的,在这里感谢我校的大佬陈敬辉,我研究了他的代码,我想问他一句:四百多行的代码,你这是抄谁的?这题一般的省一是绝对不会的。
#include<cstdio> #include<algorithm> using namespace std;class fenshu{ private:int fuhao,fenmu,fenzi; public:void clean(void){fenzi=1,fenmu=1,fenzi=0;} void prepare(int s,int d,int n){if(!d) return; fuhao=s,fenzi=n,fenmu=d; int gcd=__gcd(fenzi,fenmu); fenzi/=gcd,fenmu/=gcd; }int FUHAO(){return fuhao;} int FENZI(){return fenzi;} int FENMU(){return fenmu;} void Abs(void){fuhao=1;} fenshu operator+(fenshu X){fenshu ans; ans.clean(),ans.fenmu=fenmu*X.fenmu,ans.fenzi=0; fuhao?ans.fenzi+=fenzi*X.fenmu:ans.fenzi-=fenzi*X.fenmu; X.fuhao?ans.fenzi+=X.fenzi*fenmu:ans.fenzi-=X.fenzi*fenmu; ans.fuhao=ans.fenzi>=0?1:0; if(!ans.fuhao) ans.fenzi=-ans.fenzi; int gcd=__gcd(ans.fenzi,ans.fenmu); ans.fenzi/=gcd,ans.fenmu/=gcd; return ans; }fenshu operator-(fenshu X){fenshu ans; ans.clean(),ans.fenmu=fenmu*X.fenmu,ans.fenzi=0; fuhao?ans.fenzi+=fenzi*X.fenmu:ans.fenzi-=fenzi*X.fenmu; X.fuhao?ans.fenzi-=X.fenzi*fenmu:ans.fenzi+=X.fenzi*fenmu; ans.fuhao=ans.fenzi>=0?1:0; if(!ans.fuhao) ans.fenzi=-ans.fenzi; int gcd=__gcd(ans.fenzi,ans.fenmu); ans.fenzi/=gcd,ans.fenmu/=gcd; return ans; }fenshu operator*(fenshu X){fenshu ans; ans.clean(),ans.fenmu=fenmu*X.fenmu,ans.fenzi=fenzi*X.fenzi; ans.fuhao=fuhao==X.fuhao?1:0; if(ans.fenmu<0) ans.fenmu=-ans.fenmu; if(ans.fenzi<0) ans.fenzi=-ans.fenzi; int gcd=__gcd(ans.fenzi,ans.fenmu); ans.fenzi/=gcd,ans.fenmu/=gcd; return ans; }fenshu operator/(fenshu X){fenshu ans; ans.clean(),ans.fenmu=fenmu*X.fenzi,ans.fenzi=fenzi*X.fenmu; ans.fuhao=fuhao==X.fuhao?1:0; if(ans.fenmu<0) ans.fenmu=-ans.fenmu; if(ans.fenzi<0) ans.fenzi=-ans.fenzi; int gcd=__gcd(ans.fenzi,ans.fenmu); ans.fenzi/=gcd,ans.fenmu/=gcd; return ans; }bool operator==(fenshu X){return fenzi==X.fenzi&&fenmu==X.fenmu;} bool operator>=(fenshu X){fenshu ans; ans.clean(),ans.fenmu=fenmu*X.fenmu,ans.fenzi=0; fuhao?ans.fenzi+=fenzi*X.fenmu:ans.fenzi-=fenzi*X.fenmu; X.fuhao?ans.fenzi-=X.fenzi*fenmu:ans.fenzi+=X.fenzi*fenmu; return ans.fenzi>=0; }bool operator <= (fenshu X){fenshu ans; ans.clean(),ans.fenmu=fenmu*X.fenmu,ans.fenzi=0; fuhao?ans.fenzi+=fenzi*X.fenmu:ans.fenzi-=fenzi*X.fenmu; X.fuhao?ans.fenzi-=X.fenzi*fenmu:ans.fenzi+=X.fenzi*fenmu; return ans.fenzi<=0; }bool operator>(fenshu X){fenshu ans; ans.clean(),ans.fenmu=fenmu*X.fenmu,ans.fenzi=0; fuhao?ans.fenzi+=fenzi*X.fenmu:ans.fenzi-=fenzi*X.fenmu; X.fuhao?ans.fenzi-=X.fenzi*fenmu:ans.fenzi+=X.fenzi*fenmu; return ans.fenzi>0; }bool operator<(fenshu X){fenshu ans; ans.clean(),ans.fenmu=fenmu*X.fenmu,ans.fenzi=0; fuhao?ans.fenzi+=fenzi*X.fenmu:ans.fenzi-=fenzi*X.fenmu; X.fuhao?ans.fenzi-=X.fenzi*fenmu:ans.fenzi+=X.fenzi*fenmu; return ans.fenzi<0; }void read(){char s[51];scanf("%s",s);int t=0; s[0]=='-'?fuhao=0,t=1:fuhao=1,t=0; fenmu=fenzi=0; while(s[t]^'/') fenzi=fenzi*10+s[t]-'0',++t; ++t;while(s[t]^'\0') fenmu=fenmu*10+s[t]-'0',++t; if(!fenmu){clean();return;} int gcd=__gcd(fenzi,fenmu); fenzi/=gcd,fenmu/=gcd;} }hour_minute,hour_second,minute_second,hour_0,minute_0,second_0,l59,step_s,zero,one,full,full6,full12,full30,full60,full3600,temp; class time{public:int hour,minute,second; bool operator!=(time x){return hour^x.hour||minute^x.minute||second!=x.second;} friend bool operator<(time x,time y){ if(x.hour^y.hour) return x.hour<y.hour; if(x.minute^y.minute) return x.minute<y.minute; return x.second<y.second;} }anss[43200],_anss[43200]; int _ans,T,ans; fenshu change(fenshu x){ while(x<zero) x=x+full; while(x>full) x=x-full; return x; }void check(){fenshu minute,hour; hour_0=change(second_0+hour_second); if(hour_0==change(minute_0+hour_minute)||hour_0==change(minute_0-hour_minute)){ minute=minute_0; while(minute>=full6) minute=minute-full6; minute=minute/full6*full; if(second_0==minute){ minute=minute_0,minute=minute/full6*full,hour=hour_0; while(hour>=full30) hour=hour-full30; hour=hour*full12*full60; if(hour==minute){anss[ans].hour=0; for(temp=hour_0;temp>=full30;temp=temp-full30,++anss[ans].hour); anss[ans].minute=0; for(temp=minute_0;temp>=full6;temp=temp-full6,++anss[ans].minute); anss[ans].second=0; for(temp=second_0;temp>=full6;temp=temp-full6,++anss[ans].second); ++ans; }}}hour_0=change(second_0-hour_second); if(hour_0==change(minute_0+hour_minute)||hour_0==change(minute_0-hour_minute)){ minute=minute_0; while(minute>=full6) minute=minute-full6; minute=minute/full6*full; if(second_0==minute){ minute=minute_0,minute=minute/full6*full,hour=hour_0; while(hour>=full30) hour=hour-full30; hour=hour*full12*full60; if(hour==minute){ anss[ans].hour=0; for(temp=hour_0;temp>=full30;temp=temp-full30,++anss[ans].hour); anss[ans].minute=0; for(temp=minute_0;temp>=full6;temp=temp-full6,++anss[ans].minute); anss[ans].second=0; for(temp=second_0;temp>=full6;temp=temp-full6,++anss[ans].second); ++ans; }}}}signed main(){ hour_minute.clean(),hour_second.clean(),minute_second.clean(),hour_0.clean(),minute_0.clean(); second_0.clean(),l59.clean(),l59.prepare(1,1,354),step_s.clean(),step_s.prepare(1,1,6),zero.clean(); one.clean(),full.clean(),full60.clean(),full3600.clean(),temp.clean(),full30.clean(),full6.clean(); full12.clean(),zero.prepare(1,1,0),one.prepare(1,1,1),full.prepare(1,1,360),full60.prepare(1,1,60); full3600.prepare(1,1,3600),full30.prepare(1,1,30),full6.prepare(1,1,6),full12.prepare(1,1,12); scanf("%d",&T); fenshu pd;pd.prepare(1,20,39); while(T--){ hour_minute.read(),hour_second.read(),minute_second.read(),ans=0; for(second_0.prepare(1,1,0);second_0<=l59;second_0=second_0+step_s) minute_0=change(second_0+minute_second),check(),minute_0=change(second_0-minute_second),check(); sort(anss,anss+ans); if(ans){_anss[0].hour=anss[0].hour; _anss[0].minute=anss[0].minute; _anss[0].second=anss[0].second;_ans=1; for(int i=1;i<ans;++i) if(anss[i]!=anss[i-1]){ _anss[_ans].hour=anss[i].hour; _anss[_ans].minute=anss[i].minute; _anss[_ans++].second=anss[i].second; } }printf("%d\n",_ans); for(int i=0;i<_ans;++i) printf("%02d:%02d:%02d\n",_anss[i].hour,_anss[i].minute,_anss[i].second); } }
代码说明
这篇代码挺长,这道题非常不好写。我的思路可行,正解是直接按照暴力来做,枚举可能出现的点,然后去重。我用了类模板在这里,这个东西可以在我的工程C++中看到,不过我没用自己的定义类,而是类struct的模板。
首先读入数据,这个和快读同理,注意的是\0代表的是空字符,就是空格,换行和制表符。然后我们对可能出现的时间进行变换,怎么做呢?把时间枚举出来,然后变成分数暴力判断,用operator重载。枚举的时候用了倍增的思想。最后输出的时候要排序去重,其实这里本来是重载了unique的,现在它没有了。
今天发生了一些变故,我深深的感到了人心不古。