この記事では
プログラミング学習サービスpaizaラーニングの
スキルチェックレベルアップ問題集をわかりやすく解説します!
プログラミング言語はpythonです。
今回はSランク相当の以下の問題を解説します。
他のレベルアップ問題集の解答と解説も紹介しているので
ぜひご参考ください!
またpaizaの各ランクの攻略法は
こちらで詳しく紹介しているので、ぜひご参考ください!
この問題を解くための3つのポイント
まずは「この問題を解くためのポイント」をご説明します。
問題はこちらからご確認ください。
この問題を解くためのポイントは以下の3つです。
- 与えられた整数を7で割った余りを計算
- 0~6の数字を3つ合計し、7で割った余りを計算
- 組み合わせの数を計算
与えられた整数を7で割った余りを計算
まずは「与えられた整数を7で割った余りを計算」です。
今回の問題では、入力された整数の中の3つを合計し
それが7で割り切れる組み合わせの数を計算します。
しかしそれぞれの整数ごとに場合分けを考えて
for文を使ってしまうと
おそらくランタイムエラーになってしまいます。
# 入力される整数の個数
N = int(input())
# 入力される整数のリスト
num_list = []
for _ in range(N):
num_list.append(int(input()))
# 各整数ごとにfor文で場合分けが必要になる
for文については、こちらをご参考ください!
そのため入力された整数を7で割った余り(0〜6)を計算し、回数を数え
その余りを3つ合計した値が7で割り切れるかを考えます。
すると余りは7種類しか無いので、場合分けの数を大幅に削減できます。
# 0~6の余りの回数のリスト
num_list = [0]*7
for _ in range(N):
num_list[int(input())%7] += 1
# 7種類の余り(0~6)ごとの場合分けで可能
余りの計算とリストについては、こちらをご参考ください!
0~6の数字を3つ合計し、7で割った余りを計算
次に「0~6の数字を3つ合計し、7で割った余りを計算」です。
上記で述べたとおり今回の問題では
入力された整数をそのまま合計して余りを計算すると
処理が終わらなくなってしまうので、予め7で割った余りを計算し
0~6の3つの数字を合計し、7で割り切れるかどうかを計算します。
そのため3重のfor文を使って7×7×7
の場合分けを行います。
# i,j,kは1,2,3番目に引いた整数の余り
for i in range(0, 7):
for j in range(i, 7):
for k in range(j, 7):
次に3つの整数の余りの合計が7で割り切れるかどうかで
if文を使って条件分岐を行います。
# i,j,kは1,2,3番目に引いた整数の余り
for i in range(0, 7):
for j in range(i, 7):
for k in range(j, 7):
if (i + j + k) % 7 == 0:
# 7で割り切れる組み合わせの数を計算
if文については、こちらをご参考ください!
組み合わせの数を計算する
最後は「組み合わせの数を計算」です。
余りの合計が7で割り切れる場合の組み合わせの数を計算します。
組み合わせの数の計算式は
- 3つの数が同じ場合
- 2つの数が同じ場合
- 全ての数が違う場合
の場合にそれぞれ以下のように異なります。
(同じ数)×((同じ数)-1)×((同じ数)-2)÷6
(同じ数)×((同じ数)-1)÷2×(違う数)
(違う数)×(違う数)×(違う数)
そのためif elif else文を使って条件分岐を行います。
""" totalは組み合わせの数を合計する変数 """
# 3つの数が同じ場合
if i == j == k:
total += num_list[i] * (num_list[j] - 1) * (num_list[k] - 2) // 6
# 1つ目と2つ目の数が同じ場合
elif i == j < k:
total += (num_list[i] * (num_list[j] -1) // 2) * num_list[k]
# 2つ目と3つ目の数が同じ場合
elif i < j == k:
total += num_list[i] * (num_list[j] * (num_list[k] - 1) // 2)
# すべての数が違う場合
else:
total += num_list[i] * num_list[j] * num_list[k]
2つの数が同じ場合は
- 1つ目と2つ目の数が同じ場合
- 2つ目と3つ目の数が同じ場合
の2つで条件分岐を行いました。
四則演算とif文については、こちらをご参考ください!
mod7占い (paizaランク S 相当)の解答
ではここまで紹介したポイントを使って、問題を解いていきます。
入力を受け取り、7で割った余りを計算しカウント
まずは「入力を受け取り、7で割ったあまりを計算しカウント」です。
今回の問題ではまず1行目で
以降で入力される数の個数が入力されます。
そのためinput関数を使って入力を受け取り
# 入力される数の個数
N = int(input())
標準入力と、int型などの変数の型についてはこちらをご参考ください!
次に0~6の余りが現れる回数をカウントするための
リストを用意します。
# 入力される数の個数
N = int(input())
# 0~6の余りの回数のリスト
num_list = [0]*7
リストについては、こちらをご参考ください!
そしてfor文を使って入力を受け取り
7で割ったときの余りを計算し、それぞれの回数をカウントします。
# 入力される数の個数
N = int(input())
# 0~6の余りの回数のリスト
num_list = [0]*7
# 入力された数を7で割った余りをカウント
for _ in range(N):
num_list[int(input())%7] += 1
for文については、こちらをご参考ください!
0~6の余りに対して場合分けを3回行う
次は「0~6の余りに対して場合分けを3回行う」です。
まず組み合わせの数をカウントする変数を定義し
その後for文を使って1回目の数字を
7で割ったときの余りについて場合分けを行います。
# 組み合わせの数をカウントする変数
total = 0
# 1番目の整数を7で割った余りが0~6の場合分け
for i in range(0, 7):
次に2番目と3番目の数字に対しても同様に
7で割ったときの余りに関する場合分けを考えます。
# 組み合わせの数をカウントする変数
total = 0
# 1,2,3番目の整数を7で割った余りが0~6の場合分け
for i in range(0, 7):
for j in range(i, 7):
for k in range(j, 7):
最後に3つの余りの合計を
7で割った余りが0の場合を考えるために
if文を使って条件分岐をします。
# 組み合わせの数をカウントする変数
total = 0
# 1,2,3番目の整数を7で割った余りが0~6の場合分け
for i in range(0, 7):
for j in range(i, 7):
for k in range(j, 7):
# 余りの合計を7で割った余りが0のとき
if (i + j + k) % 7 == 0:
if文についてはこちらをご参考ください!
組み合わせの数を計算して結果を出力
最後は「組み合わせの数を計算して結果を出力」です。
まず余りの合計を7で割った余りが0のときに
if elif else文を使って組み合わせの数を計算します。
# 3つの数が同じ場合
if i == j == k:
total += num_list[i] * (num_list[j] - 1) * (num_list[k] - 2) // 6
# 1つ目と2つ目の数が同じ場合
elif i == j < k:
total += (num_list[i] * (num_list[j] -1) // 2) * num_list[k]
# 2つ目と3つ目の数が同じ場合
elif i < j == k:
total += num_list[i] * (num_list[j] * (num_list[k] - 1) // 2)
# すべての数が違う場合
else:
total += num_list[i] * num_list[j] * num_list[k]
最後に結果を出力します。
# 組み合わせの数の合計を出力
print(total)
解答
まとめると解答は以下です。
# 入力される数の個数
N = int(input())
# 0~6の余りの回数のリスト
num_list = [0]*7
# 入力された数を7で割った余りをカウント
for _ in range(N):
num_list[int(input())%7] += 1
# 組み合わせの数をカウントする変数
total = 0
# 1,2,3番目の整数を7で割った余りが0~6の場合分け
for i in range(0, 7):
for j in range(i, 7):
for k in range(j, 7):
# 余りの合計を7で割った余りが0のとき
if (i + j + k) % 7 == 0:
# 3つの数が同じ場合
if i == j == k:
total += num_list[i] * (num_list[j] - 1) * (num_list[k] - 2) // 6
# 1つ目と2つ目の数が同じ場合
elif i == j < k:
total += (num_list[i] * (num_list[j] -1) // 2) * num_list[k]
# 2つ目と3つ目の数が同じ場合
elif i < j == k:
total += num_list[i] * (num_list[j] * (num_list[k] - 1) // 2)
# すべての数が違う場合
else:
total += num_list[i] * num_list[j] * num_list[k]
# 組み合わせの数の合計を出力
print(total)
ぜひご参考ください!
まとめ
今回はpaizaのスキルチェックのレベルアップ問題集の問題の中で
- mod7占い(paizaランクS相当)
の解答と解説を紹介しました。
Sランクの問題になると、まず正しい答えを出力することでさえ難しくなります。
また制限時間がかなり厳しくなってくるので
問題分の読み間違いなどの時間のロスには注意しましょう!
ぜひSランク目指してがんばってください!
また他のレベルアップ問題集の問題についての解説も、ぜひご参考ください!