C - チーム分けくじ引き / Team Assignment Lottery Editorial by admin Editorial for printing
GPT 5.2 High概要
高橋君(メンバー1)とランクが異なる相手がくじで選ばれる確率を、既約分数で求める問題です。
考察
くじで選ばれるのはメンバー \(2 \sim N\) のうちの1人で、全員が同確率 \(\frac{1}{N-1}\) で選ばれます。
したがって「ペアが成立する(=ランクが異なる)」確率は、
- 分子:\(2 \sim N\) の中で 高橋君とランクが異なる人数
- 分母:候補人数である \(N-1\)
の比になります。
つまり答えは [ \frac{#{i \in [2,N] : S_i \neq S_1}}{N-1} ] です。
素朴に S = input().split() のようにして全員分の文字列をリストにすると、\(N \le 10^6\) で入力が大きく、Pythonではメモリ使用量が増えたり速度が落ちたりしがちです(TLE/メモリ面のリスク)。
そこで、入力をバイト列として読み取り、A/B だけを数えることで、余計な文字列生成を避けて高速・省メモリに処理します。
また、出力は既約分数なので \(\gcd\) で約分が必要です。
確率が \(0\) や \(1\) のときは 0/1, 1/1 と指定されているので、そこも分岐します。
アルゴリズム
- \(N\) を読む。
- 残りの入力をバイト列として読み、
AまたはBの文字だけを順に拾う。- 1つ目に現れたランクを \(S_1\)(高橋君のランク)として記録。
- 2つ目以降(メンバー2以降)で \(S_1\) と同じランクの人数
sameを数える。
- 異なるランクの人数は
diff = (N-1) - same。 - 確率は \(\frac{\text{diff}}{N-1}\)。
diff == 0なら0/1diff == N-1なら1/1- それ以外は \(g=\gcd(\text{diff}, N-1)\) で約分して
diff/gと(N-1)/gを出力。
例:\(N=5\), ランクが A B A B B のとき
高橋君は A、メンバー2〜5は B A B B。
異なる(B)が3人なので確率は \(\frac{3}{4}\) です。
計算量
- 時間計算量: \(O(N)\)(
A/Bを \(N\) 個数えるだけ) - 空間計算量: \(O(1)\)(人数カウントなど定数個の変数のみ)
実装のポイント
入力サイズが大きいので、
split()で巨大なリストを作らず、sys.stdin.buffer.read()でまとめて読み、バイト列からA/Bのみを数えると高速です。既約分数にするために
math.gcdで約分します。diff=0(必ず不成立)やdiff=N-1(必ず成立)のケースは、指定通り0/1,1/1を出力します。ソースコード
import sys
import math
def main():
buf = sys.stdin.buffer
N_line = buf.readline()
while N_line.strip() == b"":
N_line = buf.readline()
N = int(N_line)
rest = buf.read()
s1 = None
same = 0
cnt = 0 # number of ranks read
for b in rest:
if b == 65 or b == 66: # 'A' or 'B'
cnt += 1
if cnt == 1:
s1 = b
else:
if b == s1:
same += 1
if cnt == N:
break
diff = (N - 1) - same
if diff == 0:
print("0/1")
return
if diff == N - 1:
print("1/1")
return
g = math.gcd(diff, N - 1)
print(f"{diff // g}/{(N - 1) // g}")
if __name__ == "__main__":
main()
この解説は gpt-5.2-high によって生成されました。
posted:
last update: