AtCoder Beginner Contest 190をPythonで解く

投稿日:  更新日:2022/09/02

Atcoder Python

B!
Daniel AgreloによるPixabay(https://pixabay.com/)からの画像

こんにちは, Shinoryoです.

今回はAtCoder Beginner Contest 190を, Pythonで解いてみた結果を書き連ねていこうと思います.

A - Very Very Primitive Game

愚直に条件を確認します. 基本的にはアメの個数が多い人の勝ちで, アメの個数が同じ場合にはどちらが先手かによって変わります.

# 入力
a, b, c = [int(x) for x in input().split()]
# 愚直に条件に合うかどうかを確認
if a > b:
print("Takahashi")
elif a < b:
print("Aoki")
else:
if c == 0:
print("Aoki")
else:
print("Takahashi")

B - Magic 3

各魔法に対して, ダメージを与えられる条件を満たしているかを順に確かめていきます.

# 1行目の入力
n, s, d = [int(x) for x in input().split()]
# 各魔法に関して, ダメージを与えられるかどうかを確かめる
for i in range(n):
# 魔法データの入力
x, y = [int(x) for x in input().split()]
# ダメージが通るか判定
# 通ったらYesを出力し終了
# 通らなかったらループ続行
if x < s and y > d:
print("Yes")
exit()
# 全魔法でダメージを与えられないときNoを出力
print("No")

C - Bowls and Dishes

1K16であり, ボールが置かれる場合の数(重複あり)は22K65536であるので, ボールが置かれる場合を全探索しても問題ないでしょう.

各ボールの置き方に対して, そのボールの置き方で各条件を満たすことができるかを確認し, 結果条件を満たすことができた個数を数えます. その最大値を出力すればよいです.

import itertools
# 入力
n, m = [int(x) for x in input().split()]
abmatrix = [[int(x) for x in input().split()] for _ in range(m)]
k = int(input())
cdmatrix = [[int(x) for x in input().split()] for _ in range(k)]
# 答えを入力
ans = 0
# ボールの置き方全てを全探索
for balls in itertools.product(*cdmatrix):
# 満たすことができる条件数を計算
cnt = sum(a in balls and b in balls for a, b in abmatrix)
# ansよりcntが大きければ, ansを更新
if ans < cnt:
ans = cnt
# 答えを出力
print(ans)

D - Staircase Sequences

初項A, 末項B(AB), 公差1の等差数列の和は,

(1)N=(A+B)(BA+1)2

です. よって, この問題は,

(2)(A+B)(BA+1)=2N

の整数解A, Bを求める問題になります.

A+B, BA+1はともに自然数になります*1ので, どちらも2Nの正の約数になります. 2Nを正の約数x, yに分解できたとして,

(3){A+B=xBA+1=y

A, Bについて解くと,

(4){A=xy+12B=x+y12

となります. もし, xyの偶奇が同じなら, A, Bは整数になりません. したがって, xyの偶奇は異なる必要があります. よって, この問題は, 2Nを偶奇の異なる2つの自然数x, yに分解する問題になります.

また, 2N2を必ず素因数に含みますが, その2という素因数はxyのどちらか一方にしか含まれることができません. 仮に,

  • MN2で割り切れなくなるまで割った数であるとし,
  • Mの約数をd1=1, d2, d3, d4=Mであるとし*2,
  • x2という素因数が含まれるとする

と, yとして当てはまるのはd1, d2, d3, d4のみです*3. xyが入れ替わった場合も考えると, 求める値はMの約数の2倍になります.

# 入力
n = int(input())
# nから因数2を消去する
# 消去した回数を知る必要はない
while(n % 2 == 0):
n //= 2
# nの約数の個数を調べる
# その2倍が答えである
sqn = int(n**(0.5))
print((sum(n % i == 0 for i in range(1, sqn + 1)) * 2 - (sqn * sqn == n)) * 2)

E以降

E以降は私の能力不足故に省略いたします.

参考にしたサイト等

脚注

*1 : ABがどちらも自然数である場合, これは明らかです. また, ABがどちらも自然数ではないとすると, 等差数列の和が自然数にならないのであり得ません. Bだけが自然数だとすると, 以下のようになります.

  • |A|<|B|の場合:等差数列の和は自然数になり, A+B, BA+1はともに自然数になります.
  • |A||B|の場合:等差数列の和が自然数にならないのであり得ません.

したがって, A+B, BA+1はともに自然数になります.

*2 : もちろん何個だとしても問題ないです.

*3 : xには各yに対して適切な値が当てはまります.

Search

About Me

自分の写真
理系大学生でした. Bloggerを利用して発信を行っています.

Labels

Blog Archives