先膜一波宽神Orz%%%%%
拿到这题的第一反应就是:暴力啊!感觉神奇的钟点并没有什么性质,可能卡常能过吧……所以就写了一个O(22^3*59^3)的暴力。本来想打表,但是发现代码长度有限制,写不下。写完后发现,总共只有127034种神奇的钟点,所以当k特别大时,直接输出-1就可以了。如果数据纯随机的话,2*10^9应该能骗过不少吧。然而这种并不对劲的思想显然是会被察觉的,虽然用尽各种方法卡常,但是并没有拿多少分。
下午听讲评时,宽神说:还能怎么做?暴力啊!
我:
事实上并不是神奇的卡常方法。这道题的正解竟然也是打表!不过要用到分段打表的技巧。因为可以发现,搜索时间时,已知前一个时间就可以递推出下一个时间。
这也就是说,暴力枚举可以从中间开始。这样就可以设定一个每段的大小k,只对排在第k,k*2,k*3等k的倍数打表,查询时从离查询的名次最近的表搜。这样就找到了暴力枚举(TLE)和打表(MLE或代码长度LE)的折中方法,分段打表(AC)。
#include<algorithm> #include<cmath> #include<cstdio> #include<cstdlib> #include<cstring> #include<iostream> #include<iomanip> using namespace std; int h1; int h2,h3,m1,m2,m3; int tmp1,gdc; int upl,dnl,upr,dnr; int ch1[25]={0,0,0,0,0,0,0,0,1,2,3,4,5,7,10,13}; int ch2[25]={0,0,0,4,12,7,3,0,8,0,1,0,2,0,0,3}; int ch3[25]={0,17,0,6,5,3,12,0,3,11,0,7,9,13,4,4}; int cm1[25]={1,5,11,16,22,29,37,47,3,4,8,22,52,42,10,32}; int cm2[25]={1,57,6,8,57,15,15,3,32,39,24,40,13,18,37,36}; int cm3[25]={0,34,27,54,19,36,40,7,45,34,40,22,15,48,26,24,}; inline int read() { int x=0,f=1; char ch=getchar(); while((!isdigit(ch))&&ch!='-')ch=getchar(); if(ch=='-'){f=-1,ch=getchar(); } while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } inline void write(int x) { char ch[20];int f=0; if(!x){putchar('0');return ;} if(x<0){putchar('-');x=-x;} while(x)ch[++f]=x%10+'0',x=x/10; while(f)putchar(ch[f--]); } inline void writen(int x) { char ch[20];int f=0; if(!x){putchar('0');return ;} if(x<0){putchar('-');x=-x;} while(x)ch[++f]=x%10+'0',x=x/10; while(f)putchar(ch[f--]); putchar(' '); } inline int gcd(int x,int y) { //cout<<"+"; if(x>y)swap(x,y); if(x==0)return y; return gcd(y%x,x); } void print() { if(h1<10)putchar('0'); write(h1); putchar(':'); if(m1<10)putchar('0'); write(m1); putchar(' '); if(h2<10)putchar('0'); write(h2); putchar(':'); if(m2<10)putchar('0'); write(m2); putchar(' '); if(h3<10)putchar('0'); write(h3); putchar(':'); if(m3<10)putchar('0'); writen(m3); } int main() { int t=read(); if(t>127034){writen(-1);return 0;} int h4,m4; h1=ch1[t/8000]; h2=ch2[t/8000]; h3=ch3[t/8000]; m1=cm1[t/8000]; m2=cm2[t/8000]; m3=cm3[t/8000]; int T=(t/8000)*8000-1; bool f=0; for(;h1<24;++h1) { if(f)m1=1; for(;m1<60;++m1) { if(f)h2=0; for(;h2<24;++h2) { if(h1+h2>=24)continue; if(f)m2=1; for(;m2<60;++m2) { if(f)h3=0; for(;h3<24;++h3) { if(h1+h2+h3>=24)continue; if(f)m3=1; for(;m3<60;++m3) { //print(); //if(m3==0){++T;continue;} m4=m1+m2+m3; h4=m4/60; m4=m4-h4*60; if(m4>=60 || (!m4))continue; h4+=h1+h2+h3; if(h4>=24)continue; if((!h4) && (!h1+h2+h3)) { // cout<<h1<<","; ++T; f=1; // if(t==T) { print(); goto end; } // cout<<t<<endl; continue; } tmp1=gcd(h4,m4); upl=h4/tmp1; dnl=m4/tmp1; tmp1=gcd(m1,m2);gdc=m1*m2/tmp1; tmp1=gcd(gdc,m3);dnr=gdc*m3/tmp1; upr=h1*dnr/m1+h2*dnr/m2+h3*dnr/m3; tmp1=gcd(upr,dnr); upr=upr/tmp1; dnr=dnr/tmp1; //cout<<t<<endl; if(upl==upr && dnl==dnr) { // cout<<h1<<","; ++T; f=1; // cout<<t<<endl; // if(t==T) { print(); goto end; } // if(t%10000==0)cout<<t; } } } } } } } end:return 0; } //127034
并不对劲的人好菜啊。