Posted at

AtCoderの過去問をPythonで解く(解けるとは言っていない)#ABC100

More than 1 year has passed since last update.


まえおき

勉強の為にやっているので、ググったり時には解説読みながらやっております。

ご了承ください。


A問題:Happy Birthday!

問題文からして、AとBが共に8以下である必要がある。


Birthday.py

a,b = map(int,input().split())

if (a <= 8) and (b <= 8):
print('Yay!')
else:
print(':(')


B問題:Ringo's Favorite Numbers

Nを100^D倍するだけだな!


Numbers.py

D,N = map(int,input().split())

print(N*(100**D))

当然のようにWAした。

N = 100 の時に割れる回数が一回増えてしまうので、条件を満たさなくなってしまうことを見落としていた。

本当は一般化した方が良いのだろうけど、今回は問題の制約がN ≦ 100なので


Numbers2.py

D,N = map(int,input().split())

if N == 100: N += 1
print(N*(100**D))

これでよかろう。


C問題:*3 or /2

少し考えて、3倍は気にする必要がなく、何回2で割れるかを数えるだけと気づいた。


/2.py

num = int(input())

lis = list(map(int,input().split()))

ans = 0
for i in range(num):
while lis[i]%2 == 0:
lis[i] = lis[i]/2
ans += 1
print(ans)


もっと良い書き方あるかなー。


他の方の回答を見てみる


似てるやつ


/2'.py

num = int(input())

lis = map(int,input().split())

ans = 0
for number in lis:
while number%2 == 0:
number /= 2
ans += 1


・一旦リストにしてインデックスでアクセスするより直接イテレータとして使ったほうが良い。

・なのでmapオブジェクトをlist()する必要もない。

・あれ?最初のinput()も必要なくね?


全然違うやつ


/2''.py

input();print(sum(bin(i)[::-1].index('1') for i in map(int,input().split())))


ワンライナーで書けるのかー。

内包表記がとてもPythonっぽい。

初見だと意味がわからなかったので調べてみた。

input();で標準入力の1行目をスキップしている。

map(int,input().split())の部分がイテレータ。

sum()の引数が内包表記になっている。

bin(i)[::-1]で要素を2進数にして逆順にしている。

.index('1')で何文字目に1が最初に出てくるか=何回2で割れるか。

とても勉強になりますね。

ビット演算はそこそこ頻出らしいので押さえておきたい。


D問題:Patisserie ABC

うーん、わからん。方針すらわからん。

D問題はまだまだ手が付けられそうにないので、解説と解答例を見ていくことにする。


Patisserie.py

from itertools import product

n,m = map(int,input().split())
cake = [list(map(int,input().split())) for i in range(n)]

ans = 0
for x,y,z in product([1,-1], repeat = 3):
tmp = []
for a,b,c in cake:
tmp.append(a * x + b * y + c * z)
tmp.sort(reverse= True)
ans = max(ans,sum(tmp[:m]))
print(ans)


他にもっと早いのも短いのもあるけども、可読性はこれが一番な気がした。

itertools.product()でデカルト積を生成

 詳しい説明はここを参考にしました。


product

product([1,-1], repeat = 3)

<itertools.product at 0x1ffc0b60708>

list(product([1,-1], repeat = 3))
[( 1, 1, 1),
( 1, 1, -1),
( 1, -1, 1),
( 1, -1, -1),
(-1, 1, 1),
(-1, 1, -1),
(-1, -1, 1),
(-1, -1, -1)]


こんなリストを生成しているようです。


cake

#標準入力

5 3
1 -2 3
-4 5 -6
7 -8 -9
-10 11 -12
13 -14 15

n,m = map(int,input().split())
cake = [list(map(int,input().split())) for i in range(n)]
print(cake)
[[1, -2, 3],
[-4, 5, -6],
[7, -8, 9],
[-10, 11, -12],
[13, -14, 15]]


こちらでは各ケーキのプロパティを二次元配列にしている。

これらを掛け合わせて8通りの全探索をする。

2重for文で同じインデックスの要素を掛けて足してtmpappend()して降順ソートしてm個足す。

sum(tmp[:m])はとてもオシャレでいいですね。

ans = max(ans, x)も便利そうです。

if ans < x:ans = xみたいなことせずに済みそう。

やはり他人のコード読むのが一番勉強になる。

P○izaは課金しないと模範解答見れないのでやはりAtCoderが良いのかな。