mery's Notes

めりーがプログラミングしたりします。

MENU

AtCoder Beginner Contest (ABC) 188 PythonでA,B,C問題解いてみた 解説あり

前回解いたやつ

mery-kirokudayo.hateblo.jp

f:id:mery_poke:20211101225212p:plain

こんにちは。メリーです。
google adsenseの審査に落ちたので原因究明中です。
いろいろな記事の修正が入ると思うので、よろしゅう。

そんなこんなで今日もAtCoder Beginner Contest (ABC) 188のA,B,C問題やっていきます。
今回は結構簡単でしたね。

今日も21時からABC219があるので、それに向けてやっていきましょう。

言語はPython、提出はPyPyです。

目次

A問題

問題文

A - Three-Point Shot

バスケの3ポイントシュートで逆転可能かどうか判別する問題ですね。
ブザービーターで大逆転!!」とか憧れますよね。

というわけで方針を。
1. 点差が3点差以上か否かで場合分け。
2. 場合分けにあったもので出力。
実装

x,y = map(int,input().split())
if abs(x-y) < 3:
    print("Yes")
else:
    print("No")

コードの解説です。

abs(x-y)

でx-yの絶対値をとってます。

絶対値が3未満 = 3ptシュートで逆転

点差がちょうど3点のときは逆転不可能です。
※入力例3がその例

なので、この条件。
abs使いたくないよタイプの人は

if -3 < x-y < 3:

で同じ条件が書けます。
どっちでもお好きな方で。

B問題

問題文

B - Orthogonality

2つのベクトルの内積を求めましょう問題。

こういう数学的な問題の場合って何かしら絶対にライブラリを使ったら解ける問題が多いんですよね・・・・

うわっライブラリ知らねーってなったので正攻法でやりました。

というわけで方針
1. 全探索する
2. 各Ai*Biを足し合わせる
3. 場合分けして出力
という感じですね。

Nが105 < 108なので全探索で間に合います。

というわけで実装

n = int(input())
a = [int(x) for x in input().split()]
b = [int(x) for x in input().split()]
naiseki = 0
for i in range(n):
    naiseki += a[i] * b[i]
if not(naiseki):
    print("Yes")
else:
    print("No")

ちょっとおしゃれにリスト内包表記使ってみました。

naiseki という変数に各ループごとのAi*Biを足していくイメージ。

ちょっとしたおしゃれポイントがこちら

if not(naiseki):

naiseki = 0の場合、bool型のFalseと同値なので、

if naiseki:

はFalseになる。
しかし、notで反転させることで、naiseki = 0の場合にTrueを返すので、

if naiseki == 0:

と同様の処理ができるようになるのだ。

スマートなコードが書けると気持ちよくなれるので、意識してみると楽しくなりますよ。

ちなみに、numpyを使用した場合はこんなコードになります。

import numpy as np
n = int(input())
a = [int(x) for x in input().split()]
b = [int(x) for x in input().split()]

c =  np.dot(a,b)

if not(c):
    print("Yes")
else:
    print("No")

for文でループしなくてもいいのは楽ですよね。

C問題

問題文

C - ABC Tournament

トーナメントで誰が準優勝するのか問題ですね。

最大でも216 = 65536 < 108なので、全探索でも間に合います。

しかし、おしゃれにやりたい今日この頃!!
準優勝するのは最強さんと別のブロックの最強さんその2なので、そいつを求める方針でやります。

方針
1. 最強さんのいるブロックを求める
2. 最強さんのいないブロックでの最強を求める
3. 2を出力
という方針でやります。

実装

n = int(input())
a = [int(x) for x in input().split()]
m = max(a)
# 右半分
if a.index(m) < 2**n//2:
    print(a.index(max(a[2**n//2:]))+1)
else:
    print(a.index(max(a[:2**n//2]))+1)

if文の解説ですね。

if a.index(m) < 2**n//2:

最強さんが左半分のブロックにいるということです。
なので、右ブロックの最強を求めます。
それがこれ。

max(a[2**n//2:])

で、こいつの選手番号がこれ。

a.index(max(a[:2**n//2]))+1

※ 最後に+1が付いているのは、配列aが0始まりのため。
  出力するのは1始まりの選手番号

elseはこれらの反対のことをやっているだけです。

このやり方ならループを回さないので、実行制限にもかからずにおしゃれですね。

今日はここまでで。

それでは。