こんにちは, Shinoryoです.
今回はAtCoder Beginner Contest 194を, Pythonで解いてみた結果を書き連ねていこうと思います.
AtCoder Beginner Contest 194 - AtCoder
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
目次[非表示]
A - I Scream
条件を書いてif文で分岐させれば問題ないです.
# 入力 | |
A, B = [int(x) for x in input().split()] | |
# 出力 | |
if A + B >= 15 and B >= 8: | |
print(1) | |
elif A + B >= 10 and B >= 3: | |
print(2) | |
elif A + B >= 3: | |
print(3) | |
else: | |
print(4) |
B - Job Assignment
考え方はいくつかあります.
計算にちょっと時間がかかる方法
まずは,
- 1人でどちらの仕事もやるパターン
- 2人でどちらの仕事もやるパターン
の全場合を探索し, 最小値を出す方法です. 1人でどちらの仕事もやるパターンを全て調べるのに
import itertools | |
# 入力 | |
N = int(input()) | |
A = [] | |
B = [] | |
for _ in range(N): | |
A_i, B_i = [int(x) for x in input().split()] | |
A.append(A_i) | |
B.append(B_i) | |
# 答えを格納する変数 | |
# 10^6はかからないと踏んで | |
ans = 10**6 | |
# 1人で行う場合を探索 | |
for i in range(N): | |
ans = min(ans, A[i] + B[i]) | |
# 2人で行う場合を探索 | |
for i,j in itertools.permutations(range(N),2): | |
ans = min(ans, max(A[i], B[j])) | |
# 出力 | |
print(ans) |
計算にそこまで時間がかからない方法
2人でどちらの仕事もやるパターンを全探索しないでやることもできますね.
- 1人でどちらの仕事もやるパターン
の仕事に最も時間がかからない人との組み合わせのパターン の仕事に最も時間がかからない人との組み合わせのパターン
の全場合を探索し, 最小値を出す方法です. 上記すべてのパターンを全て調べるのに
# 入力 | |
N = int(input()) | |
A = [] | |
B = [] | |
for _ in range(N): | |
A_i, B_i = [int(x) for x in input().split()] | |
A.append(A_i) | |
B.append(B_i) | |
# 答えを格納する変数 | |
# 10^6はかからないと踏んで | |
ans = 10**6 | |
# 1人で行う場合を探索 | |
for i in range(N): | |
ans = min(ans, A[i] + B[i]) | |
# 2人で行う場合を探索 | |
# Aのかかる時間が最も短い人を採用した場合 | |
# Aのかかる最も短い時間を格納 | |
A_min = 10**6 | |
# Aのかかる時間が最も短い人リストを格納 | |
A_min_number = [] | |
# A_min、A_min_numberを調査 | |
for i in range(N): | |
if A_min > A[i]: | |
A_min = A[i] | |
A_min_number = [i] | |
elif A_min == A[i]: | |
A_min_number.append(i) | |
# A_min_numberの要素数(時間最低タイが存在しないか)で場合分け | |
if len(A_min_number) > 1: | |
# 時間最低タイが存在すれば、とりあえずmin(B)でOK | |
ans = min(ans, max(A_min, min(B))) | |
else: | |
# 時間最低タイが存在しなければ、インデックスA_min_number[0]を除いたB_tempを用意しmin(B_temp) | |
ans = min(ans, max(A_min, min(B[:A_min_number[0]] + B[A_min_number[0] + 1:]))) | |
# Bのかかる時間が最も短い人を採用した場合 | |
# Bのかかる最も短い時間を格納 | |
B_min = 10**6 | |
# Bのかかる時間が最も短い人リストを格納 | |
B_min_number = [] | |
# B_min、B_min_numberを調査 | |
for i in range(N): | |
if B_min > B[i]: | |
B_min = B[i] | |
B_min_number = [i] | |
elif B_min == B[i]: | |
B_min_number.append(i) | |
# B_min_numberの要素数(時間最低タイが存在しないか)で場合分け | |
if len(B_min_number) > 1: | |
# 時間最低タイが存在すれば、とりあえずmin(A)でOK | |
ans = min(ans, max(B_min, min(A))) | |
else: | |
# 時間最低タイが存在しなければ、インデックスB_min_number[0]を除いたA_tempを用意しmin(A_temp) | |
ans = min(ans, max(B_min, min(A[:B_min_number[0]] + A[B_min_number[0] + 1:]))) | |
# 出力 | |
print(ans) |
上で書いたようなものをよりスマートに書き直したようなものが, AtCoderの解説に載っていました.
Editorial - AtCoder Beginner Contest 194
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
C - Squared Error
問題文にあることを律儀に実行すると,
# 入力 | |
N = int(input()) | |
A = [int(x) for x in input().split()] | |
# 答えを格納する変数 | |
ans = 0 | |
# 律儀に加えていく | |
for i in range(1,N): | |
for j in range(i): | |
ans += (A[i] - A[j])**2 | |
# 出力 | |
print(ans) |
そこで, 例えば次のように考えます.
それぞれ累積和や二乗の累積和は
# 入力 | |
N = int(input()) | |
A = [int(x) for x in input().split()] | |
# Aの累積和を格納 | |
Aruiseki = [] | |
temp = 0 | |
for i in range(N): | |
temp += A[i] | |
Aruiseki.append(temp) | |
# Aの2乗の累積和を格納 | |
Asquaredruiseki = [] | |
temp = 0 | |
for i in range(N): | |
temp += A[i]**2 | |
Asquaredruiseki.append(temp) | |
# 答えを格納する変数 | |
ans = 0 | |
# 計算 | |
for i in range(1,N): | |
ans += i * (A[i]**2) | |
ans -= 2 * A[i] * Aruiseki[i-1] | |
ans += Asquaredruiseki[i-1] | |
# 出力 | |
print(ans) |
あるいは, 次のようにも考えることができます.
ここまで変形してしまえば, ここまでスマートにコーディングすることができます.
# 入力 | |
N = int(input()) | |
A = [int(x) for x in input().split()] | |
# 出力 | |
print(N * sum([x**2 for x in A]) - sum(A)**2) |
D - Journey
最終的にグラフが連結になるためには, 最初にいる頂点
:今までに訪れたことのある頂点の集合 : の要素数
とすると, 新しい頂点に訪れる確率は
ここで, 確率
この事実を用いれば,
が, 求める答えになります. これは
# 入力 | |
N = int(input()) | |
# 答えを格納する変数 | |
ans = 0.0 | |
# 今まで訪れたことのない頂点を訪れるまでにかかる回数の期待値を加えていく | |
for i in range(1,N): | |
ans += N / (N - i) | |
# 出力 | |
print(ans) |
E以降
E以降は私の能力不足故に省略いたします.
参考にしたサイト等
- 「解説 - AtCoder Beginner Contest 194」
Editorial - AtCoder Beginner Contest 194
AtCoder is a programming contest site for anyone from beginners to experts. We hold weekly programming contests online.
- 難波博之様による「幾何分布の具体例と期待値,無記憶性について」(学びTimes:高校数学の美しい物語)
幾何分布の具体例と期待値,無記憶性について | 高校数学の美しい物語
幾何分布の期待値(平均),分散,無記憶性について3つの具体例を交えて解説します.
脚注
*1 :これは以下のようにして証明される.
Bernoulli試行(Bernoulli trial)(取り得る結果が「成功」「失敗」の2つのみであり, 各試行において成功の確率が同じであるランダム試行)を繰り返して初めて成功させるまでの試行回数
となる.
この幾何分布の期待値を計算すると,
となる.
0 件のコメント:
コメントを投稿 (Please feel free to ask me about your questions! You can use Japanese or English in the comments.)