3
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 ABC413 解いてみた(緑コーダーがPythonでABCD問題)

Posted at

AtCoder Beginner Contest 413 を解いてみました

今回はリアルタイム参加できなかったため、後日時間を取って問題を解いてみました。結果は、約90分でABCDまで4問解けました(ただし、D問題で4回WA)。

A - Content Too Large

sum(A) で配列の合計値が求められるので、それと M を比較します。

N, M = map(int, input().split())
A = list(map(int, input().split()))

# 配列Aの合計値を M と比較
sumA = sum(A)
print("Yes" if sumA <= M else "No")

B - cat 2

合成した文字列を set に入れることで、重複を取り除くことが出来ます。ちょっと無駄が多いループですが、Nが小さいので制限時間には間に合います。

N = int(input())
S = []
for i in range(N):
    S.append(input())

# 重複しないようにsetで集計する
str_set = set()

# 合成文字列を作成する
for i in range(N):
    for j in range(N):
        # 同じSのときは合成しない
        if i == j:
            continue
        str_set.add(S[i] + S[j])

print(len(str_set))

C - Large Queue

末尾に数字を追加し、先頭から数字を取り出す...ということで、両面キュー(deque)を使用します。

「5 を 4 個追加する」操作をしたい場合、[5 5 5 5] と素直に追加すると、実行時間がかかってTLEになります。

そこで、[(4, 5)] のようにタプルをキューに追加する方法を採用しました。

こうすることで、例えば「2を1000個追加する」を[(1000, 2)] と1回のキューへの追加で済ませることができます。

取り出すときも同様に、例えば 「[(1000, 2)] から500個取り出す」操作を、[(500, 2)] に変えるだけで実現できます。

from collections import deque

# 両面キュー
que = deque()

Q = int(input())
for i in range(Q):
    query = list(map(int, input().split()))
    if query[0] == 1:
        # 1 のときは末尾に追加
        c = query[1]
        x = query[2]
        que.append((c, x))
    else:
        # 2のときは k個の数字を先頭から取り出す
        k = query[1]
        answer = 0
        while k > 0 and que:
            c, x = que.popleft()
            if c <= k:
                # c個取り出しても、更に取り出せるとき
                k -= c
                answer += c * x
            else:
                # k個取り出し終えたとき
                que.appendleft((c - k, x))
                answer += k * x
                k = 0

        print(answer)

D - Make Geometric Sequence

4回間違えました。復習して、難なく解けるようになってみたいものです。

Aに含まれる数字が1種類のとき

このときは、必ず等比数列になります。

例 [2 2 2 2 2] は、初項2公比1の等比数列

Aに含まれる数字が2種類のとき

以下の条件を満たせば、等比数列になります。

  • 2種類の数字が お互いに -1 をかけたものである
  • Aの個数が偶数のとき、2種類の数が同数あればよい
    • 例 [2 -2 2 -2] (公比-1の等比数列)
  • Aの個数が奇数のとき、2種類の数の個数の差が1であればよい
    • 例 [2 -2 2 -2 2] または [-2 2 -2 2 -2]

Aに含まれる数字が3種類以上のとき

配列Aを、絶対値でソートして考えます。

A=[1 -8 -2 4 16] (絶対値でソート)-> A=[1 -2 4 -8 16]

A[1]/A[0] の比率が A[2]/A[1], A[3]/A[2], A[4]/A[3] の比率とすべて一致していれば、等比数列になります。

コンピューターの性質として、割り算をして小数になってしまうと、正確な比較ができません。そこで、以下のように式変形して、小数を使わないようにしました。

A[1] / A[0] == A[i] / A[i-1] # 小数のため誤差が出てしまう

A[1] * A[i-1] == A[0] * A[i] # 小数が出ないように判定
from collections import defaultdict

# Aが等比数列かどうかを判定するメソッド
def is_correct(A):
    
    if len(A) == 2:
        return True

    value_dict = defaultdict(int)
    abs_a = []
    for a in A:
        if a < 0:
            abs_a.append((-a, -1))
            value_dict[a] += 1
        else:
            abs_a.append((a, 1))
            value_dict[a] += 1

    # Aが1種類のときは等比数列(公比1の)
    if len(value_dict) == 1:
        return True

    # Aが2種類のときは、公比−1 の等比数列しかありえない
    if len(value_dict) == 2:
        keys = list(value_dict.keys())
        key1 = keys[0]
        key2 = keys[1]

        # 公比−1になりえるかどうか
        if key1 != key2 * -1: 
            return False

        # Aの個数が偶数 → 2つの数字の個数が同じなら、公比-1の等比数列
        if len(A) % 2 == 0 and value_dict[key1] == value_dict[key2]:
            return True
            
        # Aの個数が奇数 → 2つの数字の個数の差が1なら、等比数列
        if len(A) % 2 == 1 and ((value_dict[key1] == value_dict[key2] + 1) or (value_dict[key1] + 1 == value_dict[key2])):
            return True
        return False

    abs_a.sort()

    # Aが3種類以上のとき → 各項をチェック
    is_correct = True
    for i in range(1, len(abs_a)):
        # チェック: A[i] * A[0] == A[i-1] * A[1] なら等比数列
        if abs_a[i][0] * abs_a[i][1] * abs_a[0][0] * abs_a[0][1] == abs_a[i - 1][0] * abs_a[i - 1][1] * abs_a[1][0] * abs_a[1][1]:
            continue
        else:
            is_correct = False
            break


    return is_correct

# 各テストケースを調べる
T = int(input())
for _ in range(T):
    N = int(input())
    A = list(map(int, input().split()))

    if is_correct(A):
        print("Yes")
    else:
        print("No")
3
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
3
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?