roiti46's blog

主に競プロ問題の解説を載せてます

TopCoder SRM 426 Div2 Easy: KnockoutTourney

Div2 Easyにしてはむずかしめな気がする

問題はこちら

問題

N人で行うトーナメントをしている。出場選手はトーナメント表の左から順番に番号付けされており、あなたは番号youでライバルは番号rivalである。あなたとライバルがぶつかるのは、ともに何回勝ち進んだときであるかを答えよ。

解法

いわゆる分割統治的なアプローチで解ける。
あなたとライバルの番号が、2nの半分より多い側と少ない側分かれたとき、あなたとライバルはn回戦うとぶつかることができる。
問題ではNが2のべき乗以外の場合もありうるが、簡単のためにNをNより大きな2のべき乗に直してしまっても答えは変わらない。

def meetRival(self, N, you, rival):
    ans = 0
    n = 1
    while n < N:
        n *= 2
        ans += 1
    you -= 1; rival -= 1
    while n:
        if you / (n / 2) != rival / (n / 2): return ans
        n /= 2
        ans -= 1

まとめ

2のべき乗に直すテクは便利だ