はまやんはまやんはまやん

hamayanhamayan's blog

アナログ時計 [第4回 ドワンゴからの挑戦状 本選 A]

https://beta.atcoder.jp/contests/dwacon2018-final-open/tasks/dwacon2018_final_a

解法

https://beta.atcoder.jp/contests/dwacon2018-final-open/submissions/2065413

愚直に毎秒シミュレートして計算していく。
1分経つと大体1回は分針と秒針が重なるので、C1の上限が10^4ということは60*10^4位が経過上限ということになる。
その為、毎秒O(1)でできれば毎秒シミュレートしていくことができる。

毎秒、時間が経過する前と経過した後の針の角度を求めて、一秒の間に交差しているかを確認する。
しかし、360度で角度を求めると計算過程で小数になってしまうので、下の実装では円一周120*360度で計算している。
大小関係だけ正確であればいいので、このように考えて問題ない。
あとは、公差していたらC1,C2を減らし、マイナスになったら終了。
目が覚めた時刻に針が重なっておらず、C1==0,C2==0ならば答えを更新する。

int H, M, S, C1, C2;
const ll oneday = 12 * 60 * 60;
const ll onehour = 60 * 60;
const ll oneminute = 60;
const ll pi2 = 120 * 360;
//---------------------------------------------------------------------------------------------------
void _main() {
    cin >> H >> M >> S >> C1 >> C2;
    if (H == 12) H = 0;
 
    int dt = 0;
    int t = H * 60 * 60 + M * 60 + S;
    int ma = -1, mi = inf;
    while (1) {
        ll rh = t * pi2 / oneday;
        ll rm = (t % onehour) * pi2 / onehour;
        ll rs = (t % oneminute) * pi2 / oneminute;
 
        t++;
        dt++;
 
        ll rrh = rh + pi2 / oneday;
        ll rrm = rm + pi2 / onehour;
        ll rrs = rs + pi2 / oneminute;
 
        if (rs <= rm and rrm < rrs) C1--;
        if (rm <= rh and rrh < rrm) C2--;
 
        if (C1 == 0 and C2 == 0 and rrs % pi2 != rrm % pi2 and rrm % pi2 != rrh % pi2) {
            chmax(ma, dt);
            chmin(mi, dt);
        }
        if (C1 < 0 or C2 < 0) break;
 
        t %= oneday;
    }
 
    if (ma < 0) printf("-1\n");
    else printf("%d %d\n", mi, ma);
}