[ABC285 Python]AtCoder Beginner Contest 285 A~D問題Python解説
A問題
a, b = map(int, input().split())
lis = [(1,2),(2,4),(4,8),(4,9),(2,5),(5,10),(5,11),(1,3),(3,6),(6,12),(6,13),(3,7),(7,14),(7,15)]
if (a, b) in lis:
print("Yes")
else:
print("No")
繋がっている辺は14本しかありませんので、
全部列挙したほうがいいと思います。
繋がっている点を(小さい番号、大きい番号)でリストに保存し、
(a,b)がそのリストに存在するかどうかを確認します。
B問題
N = int(input())
S = input()
for i in range(1, N):
ans = 0
judge = False
for k in range(N-i):
# print(i,j)
if S[k] != S[k+i]:
ans = k+1
else:
break
print(ans)
B問題にしては少し難しい問題ですね。
確認する変数はlとkの2つです。
まずはlについて。
問題文にも書いてありますが、
文字列Sのi番目とi+k(1<=k<=l)番目を比較することになりますので、必然的にkとlの値は決まってきます。
全てのiについて、lの値を考えていく訳ですが、
比較した文字が違うときのlの最大値なので、
比較した文字が等しいときにlの値を出力すれば、
題意を満たすlの値を出力できます。
比べる文字はS[k]とS[k+i]になります。
C問題
S = input()
string = ["A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
# print(len(string))#26
ans = 0
# for i in range(1, len(S)):
# ans += 26**i
# print(ans)
for i in range(len(S)):
s = string.index(S[i])+1
# print(s)
ans += s*26**(len(S)-i-1)
print(ans)
文字列Sは英大文字のみから構成されているため、
文字列の長さから何問目かを考えていきましょう。
例えば入力例1のABであれば、
まず1文字目をA~Zまでカウントし、
次に2文字目をAA、ABとカウントすることでSにたどり着きます。
1文字目は26^1回、
2文字目は26^2回、
3文字目は26^3回…
となるので、
Sの長さがnだとすると、
最後の文字(ABだとしたらB)にたどり着くまでに、
26^(n-1)回かかるということになるわけです。
後は文字がA,B,Cと後ろに行くにつれ1回ずつ増えていくので、
各文字について、
「その文字がAから数えて何文字目か」×「26^(n-1)」を計算し、
答えに加算していくことで、求めることができます。
D問題
from collections import defaultdict
N = int(input())
d = defaultdict(str)
start = set()
for i in range(N):
S, T = input().split()
d[S] = T
start.add(S)
visited = set()
for start_step in start:
next_step = d[start_step]
while next_step not in visited:
visited.add(next_step)
if next_step == "":
break
next_step = d[next_step]
if next_step == start_step:
print("No")
exit()
print("Yes")
2023/01/21大変遅くなりましたが、追記しました。
ユーザー名を希望通り変更できない条件を見つけることが難しいですが、入力例2にNoとなる例が載っています。
3
a b
b c
c a
入力例2を見てみると、
a→b、b→c、c→aのように
どうやらa→aという感じでループすると条件を満たさないようです。
つまり、全てのユーザーから名前の変更をはじめて、
もしループになるような回があればNoと出力するということになります。
ループを探す手法は様々ありますが、
今回はシンプルにwhileのみで書いていきます。
先程記載した通り、すべてのユーザーを見ていけばいいのですが、
もちろんこれではTLEになりますので、工夫が必要です。
工夫する箇所を説明します。
入力例3をご覧ください。
5
aaa bbb
yyy zzz
ccc ddd
xxx yyy
bbb ccc
まずはユーザー1から見ていくと
aaa→bbb→ccc→ddd
となります。
ここまでループはなさそうです。
次にちょっと飛ばしてユーザー5をご覧ください。
ユーザー5は
bbb→ccc→ddd
となりますね。
お気づきになったかもしれませんが、
ユーザー5は既にユーザー1の時に見ているので、
別に調べなくていいということが分かります。
つまり、よくDFS等で見られますが、
既に見たユーザー名は保存しておいて、
二重で調べないようにするというのが今回の工夫する点です。
では、実際にスクリプトに書き起こします。
ユーザー名の変更希望は辞書型で保存しておきましょう。
そして元のユーザー名を全て調べるので、start変数に保存しておきます。
さらに、先ほどお伝えした既に見たユーザー名を保存するために
変数visitedをset型で作っておきます。
あるユーザー名start_stepを取得し、
取得したユーザー名のユーザーが希望する新ユーザー名next_stepも同時に取得します。
next_stepはこれから調べるので、visitedに追加します。
ここで、next_stepがユーザー名のユーザーいなければ、終了します。
次のユーザがいれば、新たにnext_stepを更新します。
最後に最初に取得したstart_stepと一致しているかを確認し、
一致している場合はループが確認できるので、Noと判断するというプログラムになります。
この記事が気に入ったらサポートをしてみませんか?