并不对劲的bjwc d4t1

先膜一波宽神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('\n');
}
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
View Code

并不对劲的人好菜啊。

 

posted @ 2018-01-24 19:57  echo6342  阅读(337)  评论(0编辑  收藏  举报