背景
皆さんこんにちは。最近はとんでもない暑さですね、、、
さて、今日ふと、通勤中の電車の中で、勉強を頑張っている高校生を見かけました。
おそらく大学受験でしょうか。自分の頃は「夏を制するものは受験を制する」とよくいったものです。。。(泣)
さて、話は変わって、自分の高校の先生が「受験生は最後に伸びる」と言っていたのを思い出したのです。
それをうまく説明できるのではないか?
というアイデアがふと浮かんできたので、この記事を書いてみます!
問題設定
ここでは、簡単のため、以下のような問題設定にします。
- Qiita大学では、大学受験で10点満点の問題が1題のみ出題されます。そしてそれが8点以上解ければ合格です
 - 試験範囲には、覚えるべき内容が100個あります。
 - 試験本番では、その100個の中から、10個の内容を組み合わせた問題が1題出題されます。
 - 出題された10個の内容のうち、8個以上を自分が理解していれば、その分だけ部分点がもらえるとします。
 - 逆に、7個以下しか知らなければ問題は解けません。
 
このような仮定をおいてみたのには理由があります。
受験では、「〇〇という定理 / 単語を知らなかったら全く解けない」というシチュエーションがよくあると思います。
つまり、「ある程度覚えていなければ、全く問題が解けない」ということが、現実的にあり得そうです。
このような状況を数理的に考えると、面白い構造が見えてきそうです。
点数関数の定義
出題された10個の内容のうち、自分が知っていた内容の数を x  個とします。
このときに得られる点数(部分点)を関数 f(x)  で表します。
ここで仮定する採点基準は以下の通りです。
- 知っている内容が 8個以上であれば、その数だけ点数がもらえる
 - 7個以下しか知らなければ、全く点数はもらえない
 
このようなルールに基づいて、Python で関数 f(x, thresh=8) を以下のように定義できます。
def f(x, thresh=8):
    if x < thresh:
        return 0
    else:
        return x
print(f(7))  # → 0(7個しか知らないので不合格)
print(f(8))  # → 8(8個知っていれば部分点が入る)
print(f(10)) # → 10(満点)
内容を1個だけ覚えていた場合の期待得点
では、自分が100個のうち、たった1個だけ内容を覚えていたと仮定しましょう。
このとき、その覚えた1個の内容が、試験で出題される10個の中に入るかどうかが勝負になります。
パターン1:覚えた1個が出題される場合
- 出題10個のうち、その覚えている1個が含まれている
 - 残りの9個は、残りの99個から選ばれる → 組み合わせは $C(99,9) $
 
このとき、自分が知っている内容の数は $x = 1$
したがって得点は:f(1)(= 0、しきい値8未満なので)
パターン2:覚えた1個が出題されない場合
- 出題された10個の内容が、全て「覚えていない」もの
 - つまり、覚えていない99個から10個選ばれる → 組み合わせは $ C(99,10) $
 
このとき、自分が知っている内容の数は ( x = 0 )
得点は:f(0)(当然 0 点)
よって、このときの期待得点 ( E ) は:
$$
E = \frac{
C(99,10)* f(0) + C(99,9) * f(1)
}{
C(100,10)
}
$$
内容を ( n ) 個覚えていた場合の期待得点(一般化)
今度は、100 個のうち 自分が ( n ) 個の内容を覚えていた とします。
このとき、出題された 10 個のうち、自分の知っている内容が ( j ) 個含まれる確率は、超幾何分布に従い:
$$
P(j; n) =\frac{C(n,j)* C(100 - n,10 - j)}{C(100,10)}
$$
ここで、取りうる ( j ) の範囲は
- $( j_{\min} = \max(0,n - 90) ) $
 - $( j_{\max} = \min(n,10) )$
 
期待得点の計算式
得点関数 $f(j)$ による期待得点 $E(n)$ は:
$$
E(n) =\sum_{j=j_{\min}}^{j_{\max}} P(j; n)* f(j)
=
\sum_{j=j_{\min}}^{j_{\max}}
\frac{C(n,j)\ *C(100 - n,10 - j)}{C(100, 10)}*f(j)
$$
Python 実装例
import matplotlib.pyplot as plt
import math
def f(x,threth):
    if x<threth:
        return 0
    else:
        return x
    
def expected_score(n, thresh=8):
    total = 0
    j_min = max(0, n - 90)
    j_max = min(10, n)
    for j in range(j_min, j_max + 1):
        ways = math.comb(n, j) * math.comb(100 - n, 10 - j)
        total += ways * f(j, thresh)
    return total / math.comb(100, 10)
def req_average(threth):
    average=[]
    for i in range(101):
        average.append(expected_score(i,threth))
    return average
average=req_average(threth=8)
plt.plot([i for i in range(len(average))],average,label=str(8),marker="x")
plt.grid()
plt.legend()
plt.show()
シミュレーション結果(期待得点 vs 覚えている内容数)
では、実際に ( n = 0 ) から ( 100 ) までの内容を覚えていた場合の期待得点(≒合格確率)をプロットしてみましょう。
実行結果のグラフ
この図からわかる通り、覚えている内容の数(横軸)と期待得点(縦軸)は単純な比例関係ではありません。
特に、ある閾値(おそらく70〜80個前後)を超えると、急激に点数が伸び始めることがわかります。
考察(感想)
これは、受験問題は「ある程度理解していないと、まったく手が出ない」という特性があるという仮定のもと、「今頑張っているけど、イマイチ伸び悩んでいる……」という受験生の現象を説明できるかもしれません。
つまり、
- 知識がまだ少ないうちは、頑張っても点数につながりにくい
 - ある程度知識が積み上がった瞬間から、点数が一気に伸び始める
 
という非線形な性質があると考えられます。
※本記事は、受験勉強や統計学の専門家ではない一介のサラリーマンの素朴な思考実験です。
あくまで考察としてご覧いただければと思います。
最後に
もしこの記事を読んでくださっている方が、
「今はがんばっているけど、点数が伸びなくてしんどい……」という受験生であれば,今の努力は水面下で確実に積み上がっていると少しでも感じていただければ嬉しい限りです。
