Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit a249c9a

Browse files
author
Oliver Nash
committed
feat(archive/imo): formalize IMO 1998 problem 2 (#4502)
1 parent 5065471 commit a249c9a

File tree

4 files changed

+282
-0
lines changed

4 files changed

+282
-0
lines changed

archive/imo/imo1998_q2.lean

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
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+
import data.fintype.basic
7+
import data.int.parity
8+
import algebra.big_operators.order
9+
import tactic.ring
10+
import tactic.noncomm_ring
11+
12+
/-!
13+
# IMO 1998 Q2
14+
In a competition, there are `a` contestants and `b` judges, where `b ≥ 3` is an odd integer. Each
15+
judge rates each contestant as either "pass" or "fail". Suppose `k` is a number such that, for any
16+
two judges, their ratings coincide for at most `k` contestants. Prove that `k / a ≥ (b - 1) / (2b)`.
17+
18+
## Solution
19+
The problem asks us to think about triples consisting of a contestant and two judges whose ratings
20+
agree for that contestant. We thus consider the subset `A ⊆ C × JJ` of all such incidences of
21+
agreement, where `C` and `J` are the sets of contestants and judges, and `JJ = J × J − {(j, j)}`. We
22+
have natural maps: `left : A → C` and `right: A → JJ`. We count the elements of `A` in two ways: as
23+
the sum of the cardinalities of the fibres of `left` and as the sum of the cardinalities of the
24+
fibres of `right`. We obtain an upper bound on the cardinality of `A` from the count for `right`,
25+
and a lower bound from the count for `left`. These two bounds combine to the required result.
26+
27+
First consider the map `right : A → JJ`. Since the size of any fibre over a point in JJ is bounded
28+
by `k` and since `|JJ| = b^2 - b`, we obtain the upper bound: `|A| ≤ k(b^2−b)`.
29+
30+
Now consider the map `left : A → C`. The fibre over a given contestant `c ∈ C` is the set of
31+
ordered pairs of (distinct) judges who agree about `c`. We seek to bound the cardinality of this
32+
fibre from below. Minimum agreement for a contestant occurs when the judges' ratings are split as
33+
evenly as possible. Since `b` is odd, this occurs when they are divided into groups of size
34+
`(b−1)/2` and `(b+1)/2`. This corresponds to a fibre of cardinality `(b-1)^2/2` and so we obtain
35+
the lower bound: `a(b-1)^2/2 ≤ |A|`.
36+
37+
Rearranging gives the result.
38+
-/
39+
40+
open_locale classical
41+
noncomputable theory
42+
43+
/-- An ordered pair of judges. -/
44+
abbreviation judge_pair (J : Type*) := J × J
45+
46+
/-- A triple consisting of contestant together with an ordered pair of judges. -/
47+
abbreviation agreed_triple (C J : Type*) := C × (judge_pair J)
48+
49+
variables {C J : Type*} (r : C → J → Prop)
50+
51+
/-- The first judge from an ordered pair of judges. -/
52+
abbreviation judge_pair.judge₁ : judge_pair J → J := prod.fst
53+
54+
/-- The second judge from an ordered pair of judges. -/
55+
abbreviation judge_pair.judge₂ : judge_pair J → J := prod.snd
56+
57+
/-- The proposition that the judges in an ordered pair are distinct. -/
58+
abbreviation judge_pair.distinct (p : judge_pair J) := p.judge₁ ≠ p.judge₂
59+
60+
/-- The proposition that the judges in an ordered pair agree about a contestant's rating. -/
61+
abbreviation judge_pair.agree (p : judge_pair J) (c : C) := r c p.judge₁ ↔ r c p.judge₂
62+
63+
/-- The contestant from the triple consisting of a contestant and an ordered pair of judges. -/
64+
abbreviation agreed_triple.contestant : agreed_triple C J → C := prod.fst
65+
66+
/-- The ordered pair of judges from the triple consisting of a contestant and an ordered pair of
67+
judges. -/
68+
abbreviation agreed_triple.judge_pair : agreed_triple C J → judge_pair J := prod.snd
69+
70+
@[simp] lemma judge_pair.agree_iff_same_rating (p : judge_pair J) (c : C) :
71+
p.agree r c ↔ (r c p.judge₁ ↔ r c p.judge₂) := iff.rfl
72+
73+
/-- The set of contestants on which two judges agree. -/
74+
def agreed_contestants [fintype C] (p : judge_pair J) : finset C :=
75+
finset.univ.filter (λ c, p.agree r c)
76+
77+
section
78+
79+
variables [fintype J] [fintype C]
80+
81+
/-- All incidences of agreement. -/
82+
def A : finset (agreed_triple C J) := finset.univ.filter (λ (a : agreed_triple C J),
83+
a.judge_pair.agree r a.contestant ∧ a.judge_pair.distinct)
84+
85+
lemma A_maps_to_off_diag_judge_pair (a : agreed_triple C J) :
86+
a ∈ A r → a.judge_pair ∈ finset.off_diag (@finset.univ J _) :=
87+
by simp [A, finset.mem_off_diag]
88+
89+
lemma A_fibre_over_contestant (c : C) :
90+
finset.univ.filter (λ (p : judge_pair J), p.agree r c ∧ p.distinct) =
91+
((A r).filter (λ (a : agreed_triple C J), a.contestant = c)).image prod.snd :=
92+
begin
93+
ext p,
94+
simp only [A, finset.mem_univ, finset.mem_filter, finset.mem_image, true_and, exists_prop],
95+
split,
96+
{ rintros ⟨h₁, h₂⟩, refine ⟨(c, p), _⟩, finish, },
97+
{ intros h, finish, },
98+
end
99+
100+
lemma A_fibre_over_contestant_card (c : C) :
101+
(finset.univ.filter (λ (p : judge_pair J), p.agree r c ∧ p.distinct)).card =
102+
((A r).filter (λ (a : agreed_triple C J), a.contestant = c)).card :=
103+
by { rw A_fibre_over_contestant r, apply finset.card_image_of_inj_on, tidy, }
104+
105+
lemma A_fibre_over_judge_pair {p : judge_pair J} (h : p.distinct) :
106+
agreed_contestants r p =
107+
((A r).filter(λ (a : agreed_triple C J), a.judge_pair = p)).image agreed_triple.contestant :=
108+
begin
109+
dunfold A agreed_contestants, ext c, split; intros h,
110+
{ rw finset.mem_image, refine ⟨⟨c, p⟩, _⟩, finish, },
111+
{ finish, },
112+
end
113+
114+
lemma A_fibre_over_judge_pair_card {p : judge_pair J} (h : p.distinct) :
115+
(agreed_contestants r p).card =
116+
((A r).filter(λ (a : agreed_triple C J), a.judge_pair = p)).card :=
117+
by { rw A_fibre_over_judge_pair r h, apply finset.card_image_of_inj_on, tidy, }
118+
119+
lemma A_card_upper_bound
120+
{k : ℕ} (hk : ∀ (p : judge_pair J), p.distinct → (agreed_contestants r p).card ≤ k) :
121+
(A r).card ≤ k * ((fintype.card J) * (fintype.card J) - (fintype.card J)) :=
122+
begin
123+
change _ ≤ k * ((finset.card _ ) * (finset.card _ ) - (finset.card _ )),
124+
rw ← finset.off_diag_card,
125+
apply finset.card_le_mul_card_image_of_maps_to (A_maps_to_off_diag_judge_pair r),
126+
intros p hp,
127+
have hp' : p.distinct, { simp [finset.mem_off_diag] at hp, exact hp, },
128+
rw ← A_fibre_over_judge_pair_card r hp', apply hk, exact hp',
129+
end
130+
131+
end
132+
133+
lemma add_sq_add_sq_sub {α : Type*} [ring α] (x y : α) :
134+
(x + y) * (x + y) + (x - y) * (x - y) = 2*x*x + 2*y*y :=
135+
by noncomm_ring
136+
137+
lemma norm_bound_of_odd_sum {x y z : ℤ} (h : x + y = 2*z + 1) :
138+
2*z*z + 2*z + 1 ≤ x*x + y*y :=
139+
begin
140+
suffices : 4*z*z + 4*z + 1 + 12*x*x + 2*y*y,
141+
{ rw ← mul_le_mul_left (@zero_lt_two _ _ int.nontrivial), convert this; ring, },
142+
have h' : (x + y) * (x + y) = 4*z*z + 4*z + 1, { rw h, ring, },
143+
rw [← add_sq_add_sq_sub, h', add_le_add_iff_left],
144+
suffices : 0 < (x - y) * (x - y), { apply int.add_one_le_of_lt this, },
145+
apply mul_self_pos, rw sub_ne_zero, apply int.ne_of_odd_sum ⟨z, h⟩,
146+
end
147+
148+
section
149+
150+
variables [fintype J]
151+
152+
lemma judge_pairs_card_lower_bound {z : ℕ} (hJ : fintype.card J = 2*z + 1) (c : C) :
153+
2*z*z + 2*z + 1 ≤ (finset.univ.filter (λ (p : judge_pair J), p.agree r c)).card :=
154+
begin
155+
let x := (finset.univ.filter (λ j, r c j)).card,
156+
let y := (finset.univ.filter (λ j, ¬ r c j)).card,
157+
have h : (finset.univ.filter (λ (p : judge_pair J), p.agree r c)).card = x*x + y*y,
158+
{ simp [← finset.filter_product_card], },
159+
rw h, apply int.le_of_coe_nat_le_coe_nat, simp only [int.coe_nat_add, int.coe_nat_mul],
160+
apply norm_bound_of_odd_sum,
161+
suffices : x + y = 2*z + 1, { simp [← int.coe_nat_add, this], },
162+
rw [finset.filter_card_add_filter_neg_card_eq_card, ← hJ], refl,
163+
end
164+
165+
lemma distinct_judge_pairs_card_lower_bound {z : ℕ} (hJ : fintype.card J = 2*z + 1) (c : C) :
166+
2*z*z ≤ (finset.univ.filter (λ (p : judge_pair J), p.agree r c ∧ p.distinct)).card :=
167+
begin
168+
let s := finset.univ.filter (λ (p : judge_pair J), p.agree r c),
169+
let t := finset.univ.filter (λ (p : judge_pair J), p.distinct),
170+
have hs : 2*z*z + 2*z + 1 ≤ s.card, { exact judge_pairs_card_lower_bound r hJ c, },
171+
have hst : s \ t = finset.univ.diag,
172+
{ ext p, split; intros,
173+
{ finish, },
174+
{ suffices : p.judge₁ = p.judge₂, { simp [this], }, finish, }, },
175+
have hst' : (s \ t).card = 2*z + 1, { rw [hst, finset.diag_card, ← hJ], refl, },
176+
rw [finset.filter_and, finset.inter_eq_sdiff_sdiff s t, finset.card_sdiff],
177+
{ rw hst', rw add_assoc at hs, apply nat.le_sub_right_of_add_le hs, },
178+
{ apply finset.sdiff_subset_self, },
179+
end
180+
181+
lemma A_card_lower_bound [fintype C] {z : ℕ} (hJ : fintype.card J = 2*z + 1) :
182+
2*z*z * (fintype.card C) ≤ (A r).card :=
183+
begin
184+
have h : ∀ a, a ∈ A r → prod.fst a ∈ @finset.univ C _, { intros, apply finset.mem_univ, },
185+
apply finset.mul_card_image_le_card_of_maps_to h,
186+
intros c hc,
187+
rw ← A_fibre_over_contestant_card,
188+
apply distinct_judge_pairs_card_lower_bound r hJ,
189+
end
190+
191+
end
192+
193+
local notation x `/` y := (x : ℚ) / y
194+
195+
lemma clear_denominators {a b k : ℕ} (ha : 0 < a) (hb : 0 < b) :
196+
(b - 1) / (2 * b) ≤ k / a ↔ (b - 1) * a ≤ k * (2 * b) :=
197+
begin
198+
rw div_le_div_iff,
199+
{ convert nat.cast_le; finish, },
200+
{ simp only [hb, zero_lt_mul_right, zero_lt_bit0, nat.cast_pos, zero_lt_one], },
201+
{ simp only [ha, nat.cast_pos], },
202+
end
203+
204+
theorem imo1998_q2 [fintype J] [fintype C]
205+
(a b k : ℕ) (hC : fintype.card C = a) (hJ : fintype.card J = b) (ha : 0 < a) (hb : odd b)
206+
(hk : ∀ (p : judge_pair J), p.distinct → (agreed_contestants r p).card ≤ k) :
207+
(b - 1) / (2 * b) ≤ k / a :=
208+
begin
209+
rw clear_denominators ha (nat.odd_gt_zero hb),
210+
obtain ⟨z, hz⟩ := hb, rw hz at hJ, rw hz,
211+
have h := le_trans (A_card_lower_bound r hJ) (A_card_upper_bound r hk),
212+
rw [hC, hJ] at h,
213+
-- We are now essentially done; we just need to bash `h` into exactly the right shape.
214+
have hl : k * ((2 * z + 1) * (2 * z + 1) - (2 * z + 1)) = (k * (2 * (2 * z + 1))) * z,
215+
{ simp only [add_mul, two_mul, mul_comm, mul_assoc], finish, },
216+
have hr : 2 * z * z * a = 2 * z * a * z, { ring, },
217+
rw [hl, hr] at h,
218+
cases z,
219+
{ simp, },
220+
{ exact le_of_mul_le_mul_right h z.succ_pos, },
221+
end

src/data/finset/basic.lean

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ Authors: Leonardo de Moura, Jeremy Avigad, Minchao Wu, Mario Carneiro
66
import data.multiset.finset_ops
77
import tactic.monotonicity
88
import tactic.apply
9+
import tactic.nth_rewrite
910

1011
/-!
1112
# Finite sets
@@ -1953,6 +1954,22 @@ ext $ λ ⟨x, y⟩, by simp only [mem_product, mem_bind, mem_image, exists_prop
19531954
@[simp] theorem card_product (s : finset α) (t : finset β) : card (s.product t) = card s * card t :=
19541955
multiset.card_product _ _
19551956

1957+
theorem filter_product (p : α → Prop) (q : β → Prop) [decidable_pred p] [decidable_pred q] :
1958+
(s.product t).filter (λ (x : α × β), p x.1 ∧ q x.2) = (s.filter p).product (t.filter q) :=
1959+
by { ext ⟨a, b⟩, simp only [mem_filter, mem_product], finish, }
1960+
1961+
lemma filter_product_card (s : finset α) (t : finset β)
1962+
(p : α → Prop) (q : β → Prop) [decidable_pred p] [decidable_pred q] :
1963+
((s.product t).filter (λ (x : α × β), p x.1 ↔ q x.2)).card =
1964+
(s.filter p).card * (t.filter q).card + (s.filter (not ∘ p)).card * (t.filter (not ∘ q)).card :=
1965+
begin
1966+
classical,
1967+
rw [← card_product, ← card_product, ← filter_product, ← filter_product, ← card_union_eq],
1968+
{ apply congr_arg, ext ⟨a, b⟩, simp only [filter_union_right, mem_filter, mem_product],
1969+
split; intros; finish, },
1970+
{ rw disjoint_iff, change _ ∩ _ = ∅, ext ⟨a, b⟩, rw mem_inter, finish, },
1971+
end
1972+
19561973
end prod
19571974

19581975
/-! ### sigma -/
@@ -2086,8 +2103,46 @@ lemma disjoint_iff_disjoint_coe {α : Type*} {a b : finset α} [decidable_eq α]
20862103
disjoint a b ↔ disjoint (↑a : set α) (↑b : set α) :=
20872104
by { rw [finset.disjoint_left, set.disjoint_left], refl }
20882105

2106+
lemma filter_card_add_filter_neg_card_eq_card {α : Type*} {s : finset α} (p : α → Prop)
2107+
[decidable_pred p] :
2108+
(s.filter p).card + (s.filter (not ∘ p)).card = s.card :=
2109+
by { classical, simp [← card_union_eq, filter_union_filter_neg_eq, disjoint_filter], }
2110+
20892111
end disjoint
20902112

2113+
section self_prod
2114+
variables (s : finset α) [decidable_eq α]
2115+
2116+
/-- Given a finite set `s`, the diagonal, `s.diag` is the set of pairs of the form `(a, a)` for
2117+
`a ∈ s`. -/
2118+
def diag := (s.product s).filter (λ (a : α × α), a.fst = a.snd)
2119+
2120+
/-- Given a finite set `s`, the off-diagonal, `s.off_diag` is the set of pairs `(a, b)` with `a ≠ b`
2121+
for `a, b ∈ s`. -/
2122+
def off_diag := (s.product s).filter (λ (a : α × α), a.fst ≠ a.snd)
2123+
2124+
@[simp] lemma mem_diag (x : α × α) : x ∈ s.diag ↔ x.1 ∈ s ∧ x.1 = x.2 :=
2125+
by { simp only [diag, mem_filter, mem_product], split; intros; finish, }
2126+
2127+
@[simp] lemma mem_off_diag (x : α × α) : x ∈ s.off_diag ↔ x.1 ∈ s ∧ x.2 ∈ s ∧ x.1 ≠ x.2 :=
2128+
by { simp only [off_diag, mem_filter, mem_product], split; intros; finish, }
2129+
2130+
@[simp] lemma diag_card : (diag s).card = s.card :=
2131+
begin
2132+
suffices : diag s = s.image (λ a, (a, a)), { rw this, apply card_image_of_inj_on, finish, },
2133+
ext ⟨a₁, a₂⟩, rw mem_diag, split; intros; finish,
2134+
end
2135+
2136+
@[simp] lemma off_diag_card : (off_diag s).card = s.card * s.card - s.card :=
2137+
begin
2138+
suffices : (diag s).card + (off_diag s).card = s.card * s.card,
2139+
{ nth_rewrite 2 ← s.diag_card, finish, },
2140+
rw ← card_product,
2141+
apply filter_card_add_filter_neg_card_eq_card,
2142+
end
2143+
2144+
end self_prod
2145+
20912146
/--
20922147
Given a set A and a set B inside it, we can shrink A to any appropriate size, and keep B
20932148
inside it.

src/data/int/parity.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ by rw [even_iff, mod_two_ne_zero]
3636
@[simp] lemma odd_iff_not_even {n : ℤ} : odd n ↔ ¬ even n :=
3737
by rw [not_even_iff, odd_iff]
3838

39+
lemma ne_of_odd_sum {x y : ℤ} (h : odd (x + y)) : x ≠ y :=
40+
by { rw odd_iff_not_even at h, intros contra, apply h, exact ⟨x, by rw [contra, two_mul]⟩, }
41+
3942
@[simp] theorem two_dvd_ne_zero {n : ℤ} : ¬ 2 ∣ n ↔ n % 2 = 1 :=
4043
not_even_iff
4144

src/data/nat/parity.lean

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,9 @@ by rw [even_iff, mod_two_ne_zero]
2828
@[simp] lemma odd_iff_not_even {n : ℕ} : odd n ↔ ¬ even n :=
2929
by rw [not_even_iff, odd_iff]
3030

31+
lemma odd_gt_zero {n : ℕ} (h : odd n) : 0 < n :=
32+
by { obtain ⟨k, hk⟩ := h, rw hk, exact succ_pos', }
33+
3134
instance : decidable_pred (even : ℕ → Prop) :=
3235
λ n, decidable_of_decidable_of_iff (by apply_instance) even_iff.symm
3336

0 commit comments

Comments
 (0)