【问题描述】
作为出题人的小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=,fenmu=,fenzi=;}
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=;}
fenshu operator+(fenshu X){fenshu ans;
ans.clean(),ans.fenmu=fenmu*X.fenmu,ans.fenzi=;
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>=?:;
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=;
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>=?:;
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?:;
if(ans.fenmu<) ans.fenmu=-ans.fenmu;
if(ans.fenzi<) 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?:;
if(ans.fenmu<) ans.fenmu=-ans.fenmu;
if(ans.fenzi<) 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=;
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>=;
}bool operator <= (fenshu X){fenshu ans;
ans.clean(),ans.fenmu=fenmu*X.fenmu,ans.fenzi=;
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<=;
}bool operator>(fenshu X){fenshu ans;
ans.clean(),ans.fenmu=fenmu*X.fenmu,ans.fenzi=;
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>;
}bool operator<(fenshu X){fenshu ans;
ans.clean(),ans.fenmu=fenmu*X.fenmu,ans.fenzi=;
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<;
}void read(){char s[];scanf("%s",s);int t=;
s[]=='-'?fuhao=,t=:fuhao=,t=;
fenmu=fenzi=;
while(s[t]^'/') fenzi=fenzi*+s[t]-'',++t;
++t;while(s[t]^'\0') fenmu=fenmu*+s[t]-'',++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[],_anss[];
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=;
for(temp=hour_0;temp>=full30;temp=temp-full30,++anss[ans].hour);
anss[ans].minute=;
for(temp=minute_0;temp>=full6;temp=temp-full6,++anss[ans].minute);
anss[ans].second=;
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=;
for(temp=hour_0;temp>=full30;temp=temp-full30,++anss[ans].hour);
anss[ans].minute=;
for(temp=minute_0;temp>=full6;temp=temp-full6,++anss[ans].minute);
anss[ans].second=;
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(,,),step_s.clean(),step_s.prepare(,,),zero.clean();
one.clean(),full.clean(),full60.clean(),full3600.clean(),temp.clean(),full30.clean(),full6.clean();
full12.clean(),zero.prepare(,,),one.prepare(,,),full.prepare(,,),full60.prepare(,,);
full3600.prepare(,,),full30.prepare(,,),full6.prepare(,,),full12.prepare(,,);
scanf("%d",&T);
fenshu pd;pd.prepare(,,);
while(T--){
hour_minute.read(),hour_second.read(),minute_second.read(),ans=;
for(second_0.prepare(,,);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[].hour=anss[].hour;
_anss[].minute=anss[].minute;
_anss[].second=anss[].second;_ans=;
for(int i=;i<ans;++i)
if(anss[i]!=anss[i-]){
_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=;i<_ans;++i)
printf("%02d:%02d:%02d\n",_anss[i].hour,_anss[i].minute,_anss[i].second);
}
}
代码说明
这篇代码挺长,这道题非常不好写。我的思路可行,正解是直接按照暴力来做,枚举可能出现的点,然后去重。我用了类模板在这里,这个东西可以在我的工程C++中看到,不过我没用自己的定义类,而是类struct的模板。
首先读入数据,这个和快读同理,注意的是\0代表的是空字符,就是空格,换行和制表符。然后我们对可能出现的时间进行变换,怎么做呢?把时间枚举出来,然后变成分数暴力判断,用operator重载。枚举的时候用了倍增的思想。最后输出的时候要排序去重,其实这里本来是重载了unique的,现在它没有了。
今天发生了一些变故,我深深的感到了人心不古。