|
| 1 | +/- |
| 2 | +Copyright (c) 2020 Oliver Nash. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Oliver Nash |
| 5 | +
|
| 6 | +! This file was ported from Lean 3 source module imo.imo1998_q2 |
| 7 | +! leanprover-community/mathlib commit 308826471968962c6b59c7ff82a22757386603e3 |
| 8 | +! Please do not edit these lines, except to modify the commit id |
| 9 | +! if you have ported upstream changes. |
| 10 | +-/ |
| 11 | +import Mathlib.Data.Fintype.Prod |
| 12 | +import Mathlib.Data.Int.Parity |
| 13 | +import Mathlib.Algebra.BigOperators.Order |
| 14 | +import Mathlib.Tactic.Ring |
| 15 | +import Mathlib.Tactic.NoncommRing |
| 16 | + |
| 17 | +/-! |
| 18 | +# IMO 1998 Q2 |
| 19 | +In a competition, there are `a` contestants and `b` judges, where `b ≥ 3` is an odd integer. Each |
| 20 | +judge rates each contestant as either "pass" or "fail". Suppose `k` is a number such that, for any |
| 21 | +two judges, their ratings coincide for at most `k` contestants. Prove that `k / a ≥ (b - 1) / (2b)`. |
| 22 | +
|
| 23 | +## Solution |
| 24 | +The problem asks us to think about triples consisting of a contestant and two judges whose ratings |
| 25 | +agree for that contestant. We thus consider the subset `A ⊆ C × JJ` of all such incidences of |
| 26 | +agreement, where `C` and `J` are the sets of contestants and judges, and `JJ = J × J - {(j, j)}`. We |
| 27 | +have natural maps: `left : A → C` and `right: A → JJ`. We count the elements of `A` in two ways: as |
| 28 | +the sum of the cardinalities of the fibres of `left` and as the sum of the cardinalities of the |
| 29 | +fibres of `right`. We obtain an upper bound on the cardinality of `A` from the count for `right`, |
| 30 | +and a lower bound from the count for `left`. These two bounds combine to the required result. |
| 31 | +
|
| 32 | +First consider the map `right : A → JJ`. Since the size of any fibre over a point in JJ is bounded |
| 33 | +by `k` and since `|JJ| = b^2 - b`, we obtain the upper bound: `|A| ≤ k(b^2-b)`. |
| 34 | +
|
| 35 | +Now consider the map `left : A → C`. The fibre over a given contestant `c ∈ C` is the set of |
| 36 | +ordered pairs of (distinct) judges who agree about `c`. We seek to bound the cardinality of this |
| 37 | +fibre from below. Minimum agreement for a contestant occurs when the judges' ratings are split as |
| 38 | +evenly as possible. Since `b` is odd, this occurs when they are divided into groups of size |
| 39 | +`(b-1)/2` and `(b+1)/2`. This corresponds to a fibre of cardinality `(b-1)^2/2` and so we obtain |
| 40 | +the lower bound: `a(b-1)^2/2 ≤ |A|`. |
| 41 | +
|
| 42 | +Rearranging gives the result. |
| 43 | +-/ |
| 44 | + |
| 45 | + |
| 46 | +-- porting note: `A` already upper case |
| 47 | +set_option linter.uppercaseLean3 false |
| 48 | + |
| 49 | +open scoped Classical |
| 50 | + |
| 51 | +variable {C J : Type _} (r : C → J → Prop) |
| 52 | + |
| 53 | +namespace Imo1998Q2 |
| 54 | + |
| 55 | +noncomputable section |
| 56 | + |
| 57 | +/-- An ordered pair of judges. -/ |
| 58 | +abbrev JudgePair (J : Type _) := |
| 59 | + J × J |
| 60 | +#align imo1998_q2.judge_pair Imo1998Q2.JudgePair |
| 61 | + |
| 62 | +/-- A triple consisting of contestant together with an ordered pair of judges. -/ |
| 63 | +abbrev AgreedTriple (C J : Type _) := |
| 64 | + C × JudgePair J |
| 65 | +#align imo1998_q2.agreed_triple Imo1998Q2.AgreedTriple |
| 66 | + |
| 67 | +/-- The first judge from an ordered pair of judges. -/ |
| 68 | +abbrev JudgePair.judge₁ : JudgePair J → J := |
| 69 | + Prod.fst |
| 70 | +#align imo1998_q2.judge_pair.judge₁ Imo1998Q2.JudgePair.judge₁ |
| 71 | + |
| 72 | +/-- The second judge from an ordered pair of judges. -/ |
| 73 | +abbrev JudgePair.judge₂ : JudgePair J → J := |
| 74 | + Prod.snd |
| 75 | +#align imo1998_q2.judge_pair.judge₂ Imo1998Q2.JudgePair.judge₂ |
| 76 | + |
| 77 | +/-- The proposition that the judges in an ordered pair are distinct. -/ |
| 78 | +abbrev JudgePair.Distinct (p : JudgePair J) := |
| 79 | + p.judge₁ ≠ p.judge₂ |
| 80 | +#align imo1998_q2.judge_pair.distinct Imo1998Q2.JudgePair.Distinct |
| 81 | + |
| 82 | +/-- The proposition that the judges in an ordered pair agree about a contestant's rating. -/ |
| 83 | +abbrev JudgePair.Agree (p : JudgePair J) (c : C) := |
| 84 | + r c p.judge₁ ↔ r c p.judge₂ |
| 85 | +#align imo1998_q2.judge_pair.agree Imo1998Q2.JudgePair.Agree |
| 86 | + |
| 87 | +/-- The contestant from the triple consisting of a contestant and an ordered pair of judges. -/ |
| 88 | +abbrev AgreedTriple.contestant : AgreedTriple C J → C := |
| 89 | + Prod.fst |
| 90 | +#align imo1998_q2.agreed_triple.contestant Imo1998Q2.AgreedTriple.contestant |
| 91 | + |
| 92 | +/-- The ordered pair of judges from the triple consisting of a contestant and an ordered pair of |
| 93 | +judges. -/ |
| 94 | +abbrev AgreedTriple.judgePair : AgreedTriple C J → JudgePair J := |
| 95 | + Prod.snd |
| 96 | +#align imo1998_q2.agreed_triple.judge_pair Imo1998Q2.AgreedTriple.judgePair |
| 97 | + |
| 98 | +@[simp] |
| 99 | +theorem JudgePair.agree_iff_same_rating (p : JudgePair J) (c : C) : |
| 100 | + p.Agree r c ↔ (r c p.judge₁ ↔ r c p.judge₂) := |
| 101 | + Iff.rfl |
| 102 | +#align imo1998_q2.judge_pair.agree_iff_same_rating Imo1998Q2.JudgePair.agree_iff_same_rating |
| 103 | + |
| 104 | +/-- The set of contestants on which two judges agree. -/ |
| 105 | +def agreedContestants [Fintype C] (p : JudgePair J) : Finset C := |
| 106 | + Finset.univ.filter fun c => p.Agree r c |
| 107 | +#align imo1998_q2.agreed_contestants Imo1998Q2.agreedContestants |
| 108 | +section |
| 109 | + |
| 110 | +variable [Fintype J] [Fintype C] |
| 111 | + |
| 112 | +/-- All incidences of agreement. -/ |
| 113 | +def A : Finset (AgreedTriple C J) := |
| 114 | + Finset.univ.filter @fun (a : AgreedTriple C J) => |
| 115 | + (a.judgePair.Agree r a.contestant ∧ a.judgePair.Distinct) |
| 116 | +#align imo1998_q2.A Imo1998Q2.A |
| 117 | + |
| 118 | +theorem A_maps_to_offDiag_judgePair (a : AgreedTriple C J) : |
| 119 | + a ∈ A r → a.judgePair ∈ Finset.offDiag (@Finset.univ J _) := by simp [A, Finset.mem_offDiag] |
| 120 | +#align imo1998_q2.A_maps_to_off_diag_judge_pair Imo1998Q2.A_maps_to_offDiag_judgePair |
| 121 | + |
| 122 | +theorem A_fibre_over_contestant (c : C) : |
| 123 | + (Finset.univ.filter fun p : JudgePair J => p.Agree r c ∧ p.Distinct) = |
| 124 | + ((A r).filter fun a : AgreedTriple C J => a.contestant = c).image Prod.snd := by |
| 125 | + ext p |
| 126 | + simp only [A, Finset.mem_univ, Finset.mem_filter, Finset.mem_image, true_and_iff, exists_prop] |
| 127 | + constructor |
| 128 | + · rintro ⟨h₁, h₂⟩; refine' ⟨(c, p), _⟩; tauto |
| 129 | + · intro h; aesop |
| 130 | +#align imo1998_q2.A_fibre_over_contestant Imo1998Q2.A_fibre_over_contestant |
| 131 | + |
| 132 | +theorem A_fibre_over_contestant_card (c : C) : |
| 133 | + (Finset.univ.filter fun p : JudgePair J => p.Agree r c ∧ p.Distinct).card = |
| 134 | + ((A r).filter fun a : AgreedTriple C J => a.contestant = c).card := by |
| 135 | + rw [A_fibre_over_contestant r] |
| 136 | + apply Finset.card_image_of_injOn |
| 137 | + -- porting note: used to be `tidy`. TODO: remove `ext` after `extCore` to `aesop`. |
| 138 | + unfold Set.InjOn; intros; ext; all_goals aesop |
| 139 | +#align imo1998_q2.A_fibre_over_contestant_card Imo1998Q2.A_fibre_over_contestant_card |
| 140 | + |
| 141 | +theorem A_fibre_over_judgePair {p : JudgePair J} (h : p.Distinct) : |
| 142 | + agreedContestants r p = ((A r).filter fun a : AgreedTriple C J => a.judgePair = p).image |
| 143 | + AgreedTriple.contestant := by |
| 144 | + dsimp only [A, agreedContestants]; ext c; constructor <;> intro h |
| 145 | + · rw [Finset.mem_image]; refine' ⟨⟨c, p⟩, _⟩; aesop |
| 146 | + -- porting note: this used to be `finish` |
| 147 | + · simp only [Finset.mem_filter, Finset.mem_image, Prod.exists] at h |
| 148 | + rcases h with ⟨_, ⟨_, ⟨_, ⟨h, _⟩⟩⟩⟩ |
| 149 | + cases h; aesop |
| 150 | +#align imo1998_q2.A_fibre_over_judge_pair Imo1998Q2.A_fibre_over_judgePair |
| 151 | + |
| 152 | +theorem A_fibre_over_judgePair_card {p : JudgePair J} (h : p.Distinct) : |
| 153 | + (agreedContestants r p).card = |
| 154 | + ((A r).filter fun a : AgreedTriple C J => a.judgePair = p).card := by |
| 155 | + rw [A_fibre_over_judgePair r h] |
| 156 | + apply Finset.card_image_of_injOn |
| 157 | + -- porting note: used to be `tidy` |
| 158 | + unfold Set.InjOn; intros; ext; all_goals aesop |
| 159 | +#align imo1998_q2.A_fibre_over_judge_pair_card Imo1998Q2.A_fibre_over_judgePair_card |
| 160 | + |
| 161 | +theorem A_card_upper_bound {k : ℕ} |
| 162 | + (hk : ∀ p : JudgePair J, p.Distinct → (agreedContestants r p).card ≤ k) : |
| 163 | + (A r).card ≤ k * (Fintype.card J * Fintype.card J - Fintype.card J) := by |
| 164 | + change _ ≤ k * (Finset.card _ * Finset.card _ - Finset.card _) |
| 165 | + rw [← Finset.offDiag_card] |
| 166 | + apply Finset.card_le_mul_card_image_of_maps_to (A_maps_to_offDiag_judgePair r) |
| 167 | + intro p hp |
| 168 | + have hp' : p.Distinct := by simp [Finset.mem_offDiag] at hp ; exact hp |
| 169 | + rw [← A_fibre_over_judgePair_card r hp']; apply hk; exact hp' |
| 170 | +#align imo1998_q2.A_card_upper_bound Imo1998Q2.A_card_upper_bound |
| 171 | + |
| 172 | +end |
| 173 | + |
| 174 | +theorem add_sq_add_sq_sub {α : Type _} [Ring α] (x y : α) : |
| 175 | + (x + y) * (x + y) + (x - y) * (x - y) = 2 * x * x + 2 * y * y := by noncomm_ring |
| 176 | +#align imo1998_q2.add_sq_add_sq_sub Imo1998Q2.add_sq_add_sq_sub |
| 177 | + |
| 178 | +theorem norm_bound_of_odd_sum {x y z : ℤ} (h : x + y = 2 * z + 1) : |
| 179 | + 2 * z * z + 2 * z + 1 ≤ x * x + y * y := by |
| 180 | + suffices 4 * z * z + 4 * z + 1 + 1 ≤ 2 * x * x + 2 * y * y by |
| 181 | + rw [← mul_le_mul_left (zero_lt_two' ℤ)]; ring_nf at this ⊢; exact this |
| 182 | + have h' : (x + y) * (x + y) = 4 * z * z + 4 * z + 1 := by rw [h]; ring |
| 183 | + rw [← add_sq_add_sq_sub, h', add_le_add_iff_left] |
| 184 | + suffices 0 < (x - y) * (x - y) by apply Int.add_one_le_of_lt this |
| 185 | + rw [mul_self_pos, sub_ne_zero]; apply Int.ne_of_odd_add ⟨z, h⟩ |
| 186 | +#align imo1998_q2.norm_bound_of_odd_sum Imo1998Q2.norm_bound_of_odd_sum |
| 187 | + |
| 188 | +section |
| 189 | + |
| 190 | +variable [Fintype J] |
| 191 | + |
| 192 | +theorem judge_pairs_card_lower_bound {z : ℕ} (hJ : Fintype.card J = 2 * z + 1) (c : C) : |
| 193 | + 2 * z * z + 2 * z + 1 ≤ (Finset.univ.filter fun p : JudgePair J => p.Agree r c).card := by |
| 194 | + let x := (Finset.univ.filter fun j => r c j).card |
| 195 | + let y := (Finset.univ.filter fun j => ¬r c j).card |
| 196 | + have h : (Finset.univ.filter fun p : JudgePair J => p.Agree r c).card = x * x + y * y := by |
| 197 | + simp [← Finset.filter_product_card] |
| 198 | + rw [h]; apply Int.le_of_ofNat_le_ofNat; simp only [Int.ofNat_add, Int.ofNat_mul] |
| 199 | + apply norm_bound_of_odd_sum |
| 200 | + suffices x + y = 2 * z + 1 by simp [← Int.ofNat_add, this] |
| 201 | + rw [Finset.filter_card_add_filter_neg_card_eq_card, ← hJ]; rfl |
| 202 | +#align imo1998_q2.judge_pairs_card_lower_bound Imo1998Q2.judge_pairs_card_lower_bound |
| 203 | + |
| 204 | +theorem distinct_judge_pairs_card_lower_bound {z : ℕ} (hJ : Fintype.card J = 2 * z + 1) (c : C) : |
| 205 | + 2 * z * z ≤ (Finset.univ.filter fun p : JudgePair J => p.Agree r c ∧ p.Distinct).card := by |
| 206 | + let s := Finset.univ.filter fun p : JudgePair J => p.Agree r c |
| 207 | + let t := Finset.univ.filter fun p : JudgePair J => p.Distinct |
| 208 | + have hs : 2 * z * z + 2 * z + 1 ≤ s.card := judge_pairs_card_lower_bound r hJ c |
| 209 | + have hst : s \ t = Finset.univ.diag := by |
| 210 | + ext p; constructor <;> intros |
| 211 | + · aesop |
| 212 | + · suffices p.judge₁ = p.judge₂ by simp [this] |
| 213 | + aesop |
| 214 | + have hst' : (s \ t).card = 2 * z + 1 := by rw [hst, Finset.diag_card, ← hJ]; rfl |
| 215 | + rw [Finset.filter_and, ← Finset.sdiff_sdiff_self_left s t, Finset.card_sdiff] |
| 216 | + · rw [hst']; rw [add_assoc] at hs ; apply le_tsub_of_add_le_right hs |
| 217 | + · apply Finset.sdiff_subset |
| 218 | +#align imo1998_q2.distinct_judge_pairs_card_lower_bound Imo1998Q2.distinct_judge_pairs_card_lower_bound |
| 219 | + |
| 220 | +theorem A_card_lower_bound [Fintype C] {z : ℕ} (hJ : Fintype.card J = 2 * z + 1) : |
| 221 | + 2 * z * z * Fintype.card C ≤ (A r).card := by |
| 222 | + have h : ∀ a, a ∈ A r → Prod.fst a ∈ @Finset.univ C _ := by intros; apply Finset.mem_univ |
| 223 | + apply Finset.mul_card_image_le_card_of_maps_to h |
| 224 | + intro c _ |
| 225 | + rw [← A_fibre_over_contestant_card] |
| 226 | + apply distinct_judge_pairs_card_lower_bound r hJ |
| 227 | +#align imo1998_q2.A_card_lower_bound Imo1998Q2.A_card_lower_bound |
| 228 | + |
| 229 | +end |
| 230 | + |
| 231 | +theorem clear_denominators {a b k : ℕ} (ha : 0 < a) (hb : 0 < b) : |
| 232 | + (b - 1 : ℚ) / (2 * b) ≤ k / a ↔ ((b : ℕ) - 1) * a ≤ k * (2 * b) := by |
| 233 | + rw [div_le_div_iff] |
| 234 | + -- porting note: proof used to finish with `<;> norm_cast <;> simp [ha, hb]` |
| 235 | + · convert @Nat.cast_le ℚ _ _ _ _ |
| 236 | + · aesop |
| 237 | + · norm_cast |
| 238 | + all_goals simp [ha, hb] |
| 239 | +#align imo1998_q2.clear_denominators Imo1998Q2.clear_denominators |
| 240 | + |
| 241 | +end |
| 242 | + |
| 243 | +end Imo1998Q2 |
| 244 | + |
| 245 | +open Imo1998Q2 |
| 246 | + |
| 247 | +theorem imo1998_q2 [Fintype J] [Fintype C] (a b k : ℕ) (hC : Fintype.card C = a) |
| 248 | + (hJ : Fintype.card J = b) (ha : 0 < a) (hb : Odd b) |
| 249 | + (hk : ∀ p : JudgePair J, p.Distinct → (agreedContestants r p).card ≤ k) : |
| 250 | + (b - 1 : ℚ) / (2 * b) ≤ k / a := by |
| 251 | + rw [clear_denominators ha hb.pos] |
| 252 | + obtain ⟨z, hz⟩ := hb; rw [hz] at hJ ; rw [hz] |
| 253 | + have h := le_trans (A_card_lower_bound r hJ) (A_card_upper_bound r hk) |
| 254 | + rw [hC, hJ] at h |
| 255 | + -- We are now essentially done; we just need to bash `h` into exactly the right shape. |
| 256 | + have hl : k * ((2 * z + 1) * (2 * z + 1) - (2 * z + 1)) = k * (2 * (2 * z + 1)) * z := by |
| 257 | + have : 0 < 2 * z + 1 := by aesop |
| 258 | + simp only [mul_comm, add_mul, one_mul, nonpos_iff_eq_zero, add_tsub_cancel_right]; ring |
| 259 | + have hr : 2 * z * z * a = 2 * z * a * z := by ring |
| 260 | + rw [hl, hr] at h |
| 261 | + cases' z with z |
| 262 | + · simp |
| 263 | + · exact le_of_mul_le_mul_right h z.succ_pos |
| 264 | +#align imo1998_q2 imo1998_q2 |
0 commit comments