AtCoder Beginner Contest 174 - AtCoder image

B - Distance

  • 平方根は使いません python
def main():
    N, D = map(int, input().split())
    count = 0
    for _i in range(N):
        X, Y = map(int, input().split())
        if X * X + Y * Y <= D * D:
            count += 1

    print(count)

C - Repsept

  • image
  • 高々10^6なので順番に見ていけばいいだけなのだけど、到達しないケースがあるのが問題
    • 訪問済みの剰余をマークして真面目にループ検出した
    • たどり着けるならK回目までにたどり着くので「K回目までにたどり着かなかったら到達不能と判断」でもよかったか
  • Twitterを見てると「なぜ剰余?」的な意見があったので少し補足
    • この数列は「前の数を10倍して7を足す」という操作を繰り返したもの
    • 「Kの倍数」とは「Kで割ったあまりが0である数」
    • 前の数の余りから次の数の余りがわかる
      • 数列の各項を具体的に作らなくても、その余りだけわかればよい
      • 大きな数を直接扱わなくてよい
    • 余りが0になったらそれが探してた「Kの倍数」
    • 余り0の数がみつかる前に、一度見た余りがまた出てきた場合、そこから先は同じことの繰り返しなので永遠に0に到達しない
    • 余りはK通りしかないので、K回目までに結論が出る python
def solve(K):
    visited = [False] * K
    p = 7 % K
    for i in range(K):
        if p == 0:
            return i + 1
        if visited[p]:
            return -1
        visited[p] = True
        p = (p * 10 + 7) % K
  • Q: 「K番目までにたどり着くことはわかっているので「たどり着かなかったらループだと判断」でもよかったか」
    • Yes、下記でACすることを確認した python
def solve(K):
    p = 7 % K
    for i in range(K):
        if p == 0:
            return i + 1
        p = (p * 10 + 7) % K
    return -1
  • 言及されてたことに気づいた

    • http://vvvvvv.sakura.ne.jp/ds14050/diary/20200803.html
    • なるほど、そういう解き方、面白い。
    • image
    • こういう筆算を考えた時、一の位ははてなが1個なので7に確定し、K X1の一の位が7になるX1も存在するなら一通りになる
    • X1が確定すると上1行が確定するので、次は2行目について「10の位ははてなが1個だから確定する」となる
    • このアルゴリズムが停止するのかどうかを考えてて気づいた
      • 「余りの列はK番目までに0になるか、循環するかどちらか」の「循環する」に別の表現ができる
      • 7がn個続いた数Aと、もっとたくさん続いた数BとでKでの余りが同じ場合、B-AはKの倍数
      • B-Aは、Bより小さな7が続く数に10^nを掛けた数なので「Bまでに余り0が見つかってない」という条件から、Kは10^nの約数
      • Kが1の時を除いてKの下一桁が偶数か5になる
      • このアルゴリズムでは「掛け算結果の下一桁が7にならない」ので速やかに停止してる
      • そこで停止しなかったものに関しては短いループに入らないことが保証されているので、K回目までに解にたどりつく
  • ABC174D AC

  • ABC174E AC after contest

  • ABC174F