くふむ

けふぇめ

WBC004 A - 79 Good 解説

2021年3月18日に開かれたウインドベル(@Twi_Stamp)主催の競プロ有志コンテストWind Bel Contest 004 – Good Bye 2A Day 2の解説です。

問題文

あなたは東京大学の教員です。あなたが開講した科目では、N 人の学生が受講し、学生 i (1≤i≤N) の成績は A_i(0≤Ai≤100) でした。

しかし、東京大学には「優3割規定」というルールがあります。「優3割規定」とは、『 80 点以上の成績がつく学生の人数は受講者全体の 30\% 以下でなければならない』というルールです。このルールに違反すると、怒られが発生します。

怒られるのは嫌なので、あなたは「優3割規定」に違反しないように成績をつけ直すことにしました。あなたは任意の学生の点数を 79 点に変えることができます。最低で何人の学生の点数を 79 点に変えれば「優3割規定」をみたすことができるか求めてください。

制約

  • 1 \leq N \leq 14010
  • 0 \leq A_i \leq 100
  • 入力はすべて整数

解説

「あなた」の目的は、「優3割規定」を満たすこと──つまり、 80 点以上の人数全体の 30\% 以下に抑えることです。

80 点以上の人数は、 A_i の数字をforループなどで全部見て数えればよいです。

上限人数は、全体の人数の 30\% なので、N\times\frac{30}{100} です。このままだと「 12.333\dots 人」のように小数になってしまって扱いづらいので、小数点以下を切り捨てて \lfloor N\times\frac{30}{100}\rfloor としておくとよいでしょう。

こうして求めた結果が (80 点以上の人数)\leq(上限人数) となっていたら、最初から「優3割規定」を満たしているので何もする必要はなく、答えは 0 になります。

問題は (80 点以上の人数)>(上限人数) のときです。「優3割規定」を守るためには、 (80 点以上の人数) を何とかして減らさなければなりません。ここで、学生の点数を 79 点に変える能力の出番です。このアビリティをある学生に使ったとき何が起きるのか、学生の元の点数に着目して考えてみましょう。

  • 79 点以下:何も起こらない
  • 80 点以上:80 点以上の人数1 人減る

よって、この問題は「80点以上の学生を好きなだけ減らすことができる。何人減らせば上限人数以下になるか」という問題であることが分かりました。これは (80 点以上の人数)-(上限人数) で計算できます。

実装例

解説通りの実装例

import math

def solve():
    # input
    n = int(input())
    a = list(map(int, input().split()))

    # 80点以上の人数
    yu_cnt = 0
    for score in a:
        if score >= 80:
            yu_cnt += 1

    # 上限人数
    yu_max = math.floor(0.3 * n)

    # 答えの計算
    if yu_cnt <= yu_max:
        ans = 0
    else:
        ans = yu_cnt - yu_max

    # output
    print(ans)

t = int(input())
for _ in range(t): solve()

慣れた人向けの実装例

def solve():
    # input
    n = int(input())
    a = list(map(int, input().split()))

    yu_cnt = sum(x >= 80 for x in a)
    yu_max = n * 3 // 10

    ans = max(yu_cnt - yu_max, 0)

    # output
    print(ans)

t = int(input())
for _ in range(t): solve()

ちなみに、math.floor(0.3 * n)ぞわぞわする方もいるかもしれませんが、今回の制約で誤差は出ません。

ひとこと

原案でした。時期的にもセンシティブな「優3割規定」というテーマで問題を作ってしまい非常に申し訳ないと思っています。