見出し画像

[ABC291 Python]AtCoder Beginner Contest 291(Sponsored by TOYOTA SYSTEMS)A~D問題Python解説

A問題

S = list(input())

for i in range(1, len(S)+1):
    if not S[i-1].islower():
        print(i)
        break

英文字が大文字か小文字か判断するための関数がPythonにはありますので、それを使いましょう。

Sの先頭から探していき大文字が登場したらそれが何番目か出力します。
インデックスなので+1することを忘れないようにしましょう。

B問題

N = int(input())
X = list(map(int, input().split()))
X.sort()

x = X[N:-N]

# print(x)
print(sum(x)/(3*N))

ベストN人、ワーストN人を除いた選手の平均点を出力しろという問題です。

まずは評点順にソートします。
(今回の場合は小さい順でも大きい順でも構いません。)

まずは上記の選手を除くわけですが、
ワーストN人を除くには、
先頭からN+1番目からのリストを作ればいいので、
X[N:]-①
となります。
またベストN人を除くには、
末尾からN+1番目からのリストを作ればいいので、
X[:-N]-②
となります。

①と②を組み合わせると
X[N:-N]
これが今回平均を求める対象の選手のリストです。

対象の選手は問題文より全部で3N人いますので、
平均=合計÷人数で求めることができます。

C問題

N = int(input())
S = list(input())
visited = set()
x = 0
y = 0
visited.add((0, 0))
for i in S:
    if i == "R":
        x += 1
    elif i == "L":
        x -= 1
    elif i == "U":
        y += 1
    else:
        y -= 1
    if (x, y) in visited:
        print("Yes")
        exit()
    else:
        visited.add((x,y))

print("No")

N会の移動の中で移動した座標を保存しておき、
既に通ったことのある座標かどうかを確認すればよさそうです。

現在高橋君は原点にいますので、
X=0,Y=0
とします。
文字列Sの先頭から見ていき、
RだったらX+=1
LだったらX-=1
UだったらY+=1
DだったらY-=1
とします。

この今回の移動によってどこに移動してきたかが分かります。
これを既に通った座標を示すvisitedに保存しておきます。

後は高橋君が移動してきた座標がvisitedに保存されている座標と一致するならば、
同じ座標にいたことが証明されます。

D問題

MOD = 998244353

N = int(input())

cards = [tuple(map(int, input().split())) for _ in range(N)]
dp = [[0, 0] for _ in range(N)]
dp[0] = [1, 1]

for i in range(1, N):
    if cards[i-1][0] != cards[i][0]:
        dp[i][0] += dp[i-1][0]
    if cards[i-1][0] != cards[i][1]:
        dp[i][1] += dp[i-1][0]
    if cards[i-1][1] != cards[i][0]:
        dp[i][0] += dp[i-1][1]
    if cards[i-1][1] != cards[i][1]:
        dp[i][1] += dp[i-1][1]
    dp[i][0] %= MOD
    dp[i][1] %= MOD

print(sum(dp[N-1])%MOD)

2023/02/27追記しました。

DPの問題です。
全部調べなければいけないような問題はDPを疑うといいかもしれません。

問題文のとおり、N枚のカードそれぞれが表になるか裏になるかを判断すればいいのですが、
表裏に影響するのは、
「一枚前のカードの表裏の数字」
のみです。
なので、
dp[i][表、裏]とし、
dp[i][表]=i番目のカードが表の時に条件を満たすものの数
dp[i][裏]=i番目のカードが裏の時に条件を満たすものの数
として考えます。

入力例1を用いて詳しく考えてみましょう。
N = 3
cards = [[1, 2], [4, 2], [3, 4]]

まずは1枚目。
その前にカードがないので、表裏どちらでも可能です。
なので、
dp[0][表、裏] = [1, 1]
とします。

次に2枚目。
全探索すると、
(1枚目の表、2枚目の表)=(1,4),(2,4),(1,2),(2,2)
の4通り考えられます。
この中で条件を満たさないのは(2,2)だけですね。
通常は表2通り、裏2通りですが、
裏の時-1されるので、
dp[1][表、裏] = [2, 1]
となります。

最後に3枚目。
全探索すると、
(2枚目の表、3枚目の表)=(4,3),(4,4),(2,3),(2,4)
の4通り考えられます。
この中で条件を満たさないのは(4,4)です。
よって、
dp[2][表、裏] = [3, 1]
となります。

最後に条件を満たすのは、表+裏なので、
998244353で割って出力します。



この記事が気に入ったらサポートをしてみませんか?