LoginSignup
0
0

More than 1 year has passed since last update.

超初心者がAtcoder ProblemsのC問題を161回から170回までをpythonで解いてみた

Posted at

解き方を忘れないためにまとめてるだけなのでコードはめちゃくちゃ不細工です、ここもっと良くできるよって場所あったら教えていただけるとありがたいです!!

Replacing Integer

practice.py
n,k = map(int, input().split())
cnt = n//k
n -= (k*cnt)
if abs(n-k) < n:
    print(abs(n-k))
else:
    print(n)

この問題はいちいち全探索で確認していったらバカみたいに時間がかかるバッケン、最初に何回引けるかをn//kで調べ上げます。そしてnから先に調べ上げた引ける回数とkの値をかけた値を引いて、nの値を純粋な正の値でできる限り小さくしておきます。最後にnからkを引いた値を絶対値で正の値に置き換えた値と先に小さくしたnの値を比べてより小さい方を出力します。

Sum of gcd of Tuples (Easy)

practice.py
import math 

k = int(input())
total = 0
for i in range(1,k+1):
    for j in range(1,k+1):
        tmp = math.gcd(i,j)
        for l in range(1,k+1):
            total += math.gcd(tmp, l)
print(total)

古(python3.8以前)にはな、gcdに二つしか引数を渡せないという不便な不便な時代があったそうな...なので普通に引数3つ渡すとREで弾き返されます。なので、ここではユークリッドの互除法を使って3つの数字の最大公約数を求めてい、totalに追加していきましょう。最後にtotalの値を出力おわおわりです。計算量は(K**3)とキモイですが1≤K≤200とkの値がそこまで大きくならないのでいけます。
ユークリッド兄貴について
https://www.studyplus.jp/412

management

practice.py
from collections import Counter
n = int(input())
alist = list(map(int, input().split()))
alist = Counter(alist)
for i in range(1,n+1):
    if alist[i]:
        print(alist[i])
    else:
        print(0)

この問題はまず全ての入力を受け取りalistをCounterメソッドを使って、それぞれの社員番号の直属の部下の人数を調べ上げた連想配列を作り出します。最後に、社員に直属の部下が1人以上いた場合にはその人数を出力し、存在しない場合には0を出力します。

gacha

practice.py
n = int(input())
ans = []
for i in range(n):
    prise = input()
    ans.append(prise)
print(len(set(ans)))

ん?B問題かな?普通に全部受け取って、一度set型に変換し重複を消した後のansセットの要素数を出力をしておわおわりです。

Many Requirements

practice.py
from itertools import combinations_with_replacement as cwp
n,m,q = map(int, input().split())
Q = [list(map(int, input().split())) for _ in range(q)]
ans = 0
for seq in cwp(range(1,m+1), n):
    print(seq)
    tmp = 0
    for a,b,c,d in Q:
        if seq[b-1]-seq[a-1] == c:
            tmp += d
    ans = max(ans,tmp)
print(ans) 

unidayo師匠の記事を見てほぼ丸写ししたコードです。
https://qiita.com/u2dayo/items/386142030a70d2db4e58
この人バチイケです。

Peaks

practice.py
n,m = map(int, input().split())
hlist = list(map(int, input().split()))
highests = [0]*n
for _ in range(m):
    a,b = map(int, input().split())
    highests[a-1] = max(highests[a-1], hlist[b-1])
    highests[b-1] = max(highests[b-1], hlist[a-1])
ans = 0
for i in range(n):
    if hlist[i] > highests[i]:
        ans += 1
print(ans) 

まず繋がっている道の情報を元に隣接する展望台(ベースとなる展望台は含めない)のなかで最も高い展望台の高さを保持するhighestsリストを作ります。次に道の情報を受け取って、現時点での最大値と繋がっている展望台の高さを比べて、もし新たに繋がった展望台の高さの方が大きかったら値を更新していきます(2回やるのはaの展望台をベースにした場合とbの展望台をベースにした値の更新を一つの道の情報でやってしまった方が効率が全然いいから(一粒で二度美味しい的な))。最後にベースにした展望台の高さと、ベースにした展望台に隣接した展望台の高さの最大値を比べて、もしベースにした展望台の高さの方が高かったのならばベースにした展望台は良い展望台と言えます(ansの値を1増やす)。

Skill Up

practice.py
from itertools import product
INF = 1<<60

def judge(pro):
    cost = 0
    uns = [0]*m
    for i in range(n):
        if pro[i]:
            cost += costs[i]
            for j in range(m):
                uns[j] += unss[i][j]
    for u in uns:
        if u < x:
            return INF
    return cost

n,m,x = map(int, input().split())
costs = []
unss = []
for i in range(n):
    c,*uns = map(int, input().split())
    costs.append(c)
    unss.append(uns)
ans = INF
for pro in product((0,1), repeat=n):
    ans = min(ans, judge(pro))
if ans == INF:
    print(-1)
else:
    print(ans)

みんな大好きbit全探索の問題君です。1,2,3 We love bit zentansakuuuuuuuuuu!(映画のcmの〜最高〜風)1≤N,M≤12とNの値がそこまで大きくならないことがわかるので、この問題は参考書を買うか買わないかの考え方でbit全探索してまいましょう。まず、値段とあげられる理解度の値がごっちゃになって入力されるので、をうまく使って値段とあげられる理解度で格納しておくリストを分けましょう。inputの小技で変数の前にをつけることで格納されていない全ての値を一つのリストとして格納できてしまいます。例えば『60 2 2 4』という入力を受け取った時は最初の60だけがcに格納されて、まだ格納されていない『2 2 4』が全て一つのリストとしてunsに格納されます。やったね!次にbit全探索お助けまんproductメソッドを使って考えられる購入パターンを全て洗い出します。作り出したパターンを引数としてjudgeメソッドに渡して、かかる値段の計算をしていきます。(一旦改行)
--judgeメソッドの解説--
まずかかった値段と上がった理解度の合計を格納するための変数を用意していきます。そしてfor文を回して、もし買う判定に引っ掛かったら(この場合pro[i]の値が1)理解度のところに買った本であげられる理解度のを追加し、本の値段もかかった値段のところに追加していきます。最後に、全ての理解度をfor文を回して調べ上げて1つでも理解度がxに達していないものがあったらINFを返します。
bit全探索がよくわからないbro達へ
https://qiita.com/u2dayo/items/68e35815659b1041c3c2

- : (Colon)

practice.py
import math
a,b,h,m = map(int,input().split())
degA = (60*h+m)*(0.5)
degB = m*6
deg = abs(degA-degB)
rad = math.radians(deg)
print(math.sqrt(a**2+b**2-(2*a*b*math.cos(rad))))

これはプログラミングの問題というより数学の問題ですね。単刀直入にいうと、この問題はみんな大好き余弦定理を使っておわおわりですね。公式:c2=a2+b**2−2abcosC
aとbの値は入力によって与えられている状態なので、求めないといけないのはCの角度だけです。この角度は時針と分針の角度の差によって手に入れることができます(abs(degA-degB))。ではどうやってこれらの角度を手に入れられるのか。まず時針は1時間おきにではなく1分おきに動いているというのを認識しないといけません。1分に動く時針の角度は(60分12時間)/(360°)なので0.5°です。なので時針の角度は(60(1時間単位)+分単位)*(0.5)で求めることができます。次に分針は1分間に(360/60)、6°動くので(分単位)*6と簡単に求められます。Cの角度をabs(degA-degB)で求めた値をラジアンの値に変換しないといけません(math.cosの性質上(多分...))、assholeな私はこれに全然気づかずあれーおかしいなー、壊れてるんじゃねとか言ってました... ラジアンに値を直したら、全ての値を公式に埋め込んで出力してACです。

Multiplication 3

practice.py
a,b = input().split()
a = int(a)
b = int(b[0]+b[2]+b[3])
print(a*b//100)

めっちゃ簡単これとか思って、普通に下みたいなコード書いたら何故かWAでてふぇ?ってなった

頓死したやつ.py
a,b = input().split()
a = int(a)
b = float(b)
print(int(a*b))

解説をみたところによるとコンピューターは小数のある数字を正確に表せない仕組みになっているらいしです。なので超小さな誤差がfloatにすることにより生まれてしまいます。カス問題ですね。これを期に学んでしまいましょう。なのでstr型のままbの数を100倍してa*bをやってから100で割って元の形に戻すのがACを出す方法らしいです。
詳しいことはunidayoパイセンの記事読んでください...
https://qiita.com/u2dayo/items/b84187e345cf952ffc10#c%E5%95%8F%E9%A1%8C-multiplication-3

Forbidden List

practice.py
x,n = map(int, input().split())
plist = list(map(int, input().split()))
if not x in plist:
    print(x)
    exit()
tmp1 = x
tmp2 = x
for i in range(1000):
    tmp1 -= 1
    if not tmp1 in plist:
        print(tmp1)
        exit()
    tmp2 += 1
    if not tmp2 in plist:
        print(tmp2)
        exit()

まずx自身が答えになっているケースの検証をします、もしx自身がplistに入っていないのならxが答えになるのでxを出力し処理を終わらせます。次にxの値が入った変数を2個作ります。次にリストが入っていない数字が変数に入るまでfor文を回していきます(1ループごとに最初の変数からは1を引いて、検証し、2つ目の変数からは1を足して検証するを繰り返す)。最初に1を引くのは問題の説明文で"そのような整数が複数存在する場合は、そのうち最も小さいものを答えてください。"とあるから。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0