2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AtCoder ABC414 振り返り(ほぼ緑コーダーがPythonでAB+CD問題)

Last updated at Posted at 2025-07-15

ABC414を振り返ります

今回はABまで2問解答でした。
C問題が回文の問題だったので苦手意識があり、飛ばしてD問題に取り掛かったのだけど結局わからずでした。
(C,Dはコンテスト後に復習してACしたコードを載せています)

直近の3回連続でレーティングがマイナスになってまして、今回はとうとう緑色→茶色になってしまいました...。

週末のコンテストに参加するだけだと、良くて現状維持ですね...。ちょっと過去問を解くなりしないと、現状維持も厳しいなあといった感じです。

A - Streamer Takahashi

与えられた条件を満たすリスナー数をカウントします。
(動画配信を見る人は、なぜリスナーと呼ばれるのか、以前からの不思議...ラジオの影響が大きいのでしょうか)

N, L, R = map(int, input().split())

answer = 0
for i in range(N):
    X, Y = map(int, input().split())
    if X <= L and R <= Y:
        answer += 1
print(answer)

B - String Too Long

文字列を連結していきます。ただし、入力例2にあるように、「a 1000000000000000000」みたいな文字列を連結してしまうと、処理が固まってしまいます。
そのため、復元する文字列の長さを min(101, int(l)) として、101文字以上の文字列は復元しないようにしました。

N = int(input())

answer = ""

# 文字列を復元していく
for i in range(N):
    c, l = input().split()
    # 長過ぎる文字列は101文字まで復元
    length = min(101, int(l))
    for j in range(length):
        answer += c

# 100文字を超えたらToo Long
if len(answer) > 100:
    print("Too Long")
else:
    print(answer)

C - Palindromic in Both Bases (解説AC)

問題文を見て、回避した問題です(回文に苦手意識がある)。
N<=12 という条件を見て、「10^12 の回文を一つ一つ求めていたらTLEだな...」と考えてしまったのが良くなかった。

実際は半分だけのパターンを作れば、その反転で回文がつくれるので、10^6だけ調べれば良いのでした。
例: 前半部分を123とすると、反転してくっつければ 123321 と 12321 という回文を作れる


以下のソースコードは、公式解説のYouTubeを見て書きました。
https://www.youtube.com/watch?v=rLoeRm2BXDk&t=2820s

A = int(input())
N = int(input())

# 10進数からA進数に変換する関数
def dec_to_n(num:int, base:int) -> str:
    s = ''
    while num > 0:
        s += str(num % base)
        num //= base
    return s[::-1]

# 問題の条件を満たすか判定する
def is_ok(kaibun:int, base:int) -> bool:
    # N以下の条件
    if kaibun > N:
        return False

    # A進数に変換する
    kaibun_a_str = dec_to_n(kaibun, base)

    # 変換後も回分なら、答えに加算する
    return kaibun_a_str == kaibun_a_str[::-1]        

answer = 0
for i in range(1, 10**6):
    # 回文を生成する
    # i=12 なら、1221 と 121 を作る
    str_i = str(i)
    kaibun_a = int(str_i + str_i[::-1])
    kaibun_b = int(str_i[:-1] + str_i[::-1])

    # 条件を満たすなら、答えを追加
    if is_ok(kaibun_a, A):
        answer += kaibun_a
    if is_ok(kaibun_b, A):
        answer += kaibun_b

print(answer)

D - Relative Position (解説AC)

この問題、有名な「羊羹を切る問題(001 - Yokan Party(★4))」の類題かと思って解いていたのですが、思ったように解けず...

「羊羹を切る問題」の解法(すべてのグループが長さnに収まるか?を2分探索する)だと、以下のようなケースでWAになってしまいます。

4 3
1 2 3 4
↓
[1 2] [3 4] = 2 のように、基地局2個でやってしまう
[1 2] [3] [4] = 1 と、基地局を使い切るのが正解

ではどうすればいいか。
解説を読むと「家をM個のグループに分ける」「グループ間の間隔が最大になるようにわける」と良いことがわかります。

そんな簡単な考え方で良かったのか...。

5 8 10 14 15 20 ← 家の位置(sort済)
 3 2  4  1  5   ← 家の間隔
↓
[5,8,10] [14,15] [20] と分けると、電波が届く区間の長さが(20-5)-5-4=6 となり、最小になる。
N, M = map(int, input().split())
X = list(map(int, input().split()))

# 重複を除去してソート
set_x = set(X)
X = list(set_x)
X.sort()

# 家と家の間の距離を求める
diffs = []
for i in range(1, len(X)):
    diffs.append(X[i] - X[i-1])
diffs.sort(reverse=True)

# すべての家に基地局を設置できる場合
if len(diffs) < M:
    print(0)
    exit()

# 最も左の家のから、最も右の家までの距離
home_distance = X[-1] - X[0]

# M個の基地局を設置するので、M-1個の電波が届かない区間がある
# 電波が届かない区間を、なるべく大きい区間から選ぶ
diff_distance = 0
for i in range(M-1):
    diff_distance += diffs[i]

# 全体から電波が届かない区間を引く
print(home_distance - diff_distance)
2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?