AtCoder Beginner Contest 046 - C / 050 - C

beta.atcoder.jp

答えを見たらもっと楽だった。

確認時の比を t : a、前回までの累計をT, A、前回確認時からの差分をx , yとしたとき以下が成り立てばよい。

T + x : A + y = t : a

式にしてこれを整理すると、

x =  (t * A + y * t) / a -  T 
y =  (a * T + x * a) / t -  A

となる。このとき、x, y がいずれも0または正の整数となり、最少であればよい。

xの右辺のうち、Tは整数のため、残りの部分が分子がaで割り切れることが必要であり、

(t * A) % a = m

とすると、

(m + (y * t)) % a = 0

となるyを見つければよい。

さらに、x が0または正より

x =  (t * A + y * t) / a -  T  >= 0

が成り立つため、 yについて整理すると、

y >= (T * a - t * A) / t

というyの条件ができる。y >= 0と合わせて、 これらの条件のうち大きいほうをyの検索範囲の最初にする。

ユークリッドの互除法とかをほんとは使いそうなんだけれども、 条件さえ決めてしまえば+1ずつしても間に合ってしまったのでそのまま提出。 周りの解答見るともう4倍ぐらい早いな。。

def solve(N, TAs):
    T, A = 1, 1
    for t, a in TAs:
        m = (t * A) % a
        y = max(0, (T * a - t * A) // t)
        while True:
            if (m + (y * t)) % a == 0:
                break
            y += 1
        x = (t * A + t * y) // a - T
 
        T += x
        A += y
    return T + A
  
if __name__ == "__main__":
    N = int(input())
    TAs = [(tuple)(map(int, input().split(" "))) for l in range(N)]
    print(solve(N, TAs))

beta.atcoder.jp

まずNの偶奇でAとして存在可能な数値が分かれる。 Nが偶数の時、Aの要素は奇数になり、それらはすべて2つずつ存在する。 Nが奇数の時、Aの要素は偶数になり、ちょうど真ん中にある0は一つ、それ以外はすべて二つずつ存在する。

以下でテストケースは通るんだけどAの要素の上限設定も必要だった。このままだと相異なればよいだけや。

from collections import Counter
 
 
def solve(N, As):
    c = Counter(As)
    n = 10 ** 9 + 7
    if c['0'] == N % 2 and \
            all([v == 2 and int(i) % 2 == (N + 1) % 2 for i, v in c.items() if i != '0']):
        return pow(2, N // 2, n)
 
    return 0
 
 
if __name__ == "__main__":
    N = int(input())
    As = input().split(" ")
    print(solve(N, As))