11/-
22Copyright (c) 2020 Patrick Stevens. All rights reserved.
33Released under Apache 2.0 license as described in the file LICENSE.
4- Authors: Patrick Stevens, Yury Kudryashov
4+ Authors: Patrick Stevens, Yury Kudryashov, Bhavik Mehta
55-/
66module
77
88public import Mathlib.Algebra.BigOperators.Associated
9- public import Mathlib.Algebra.Order.BigOperators.GroupWithZero.Finset
10- public import Mathlib.Algebra.Order.Ring.Abs
9+ public import Mathlib.Algebra.Squarefree.Basic
1110public import Mathlib.Data.Nat.Choose.Sum
12- public import Mathlib.Data.Nat.Choose.Dvd
1311public import Mathlib.Data.Nat.Prime.Basic
1412
13+ import Mathlib.Algebra.Order.BigOperators.GroupWithZero.Finset
14+ import Mathlib.Algebra.Order.Ring.Abs
15+ import Mathlib.Data.Nat.Choose.Dvd
16+ import Mathlib.Data.Nat.Squarefree
17+
1518/-!
1619# Primorial
1720
@@ -37,9 +40,23 @@ def primorial (n : ℕ) : ℕ := ∏ p ∈ range (n + 1) with p.Prime, p
3740
3841local notation x "#" => primorial x
3942
43+ @[simp] theorem primorial_zero : 0 # = 1 := by decide
44+
45+ @[simp] theorem primorial_one : 1 # = 1 := by decide
46+
47+ @[simp] theorem primorial_two : 2 # = 2 := by decide
48+
4049theorem primorial_pos (n : ℕ) : 0 < n# :=
4150 prod_pos fun _p hp ↦ (mem_filter.1 hp).2 .pos
4251
52+ theorem primorial_mono {m n : ℕ} (h : m ≤ n) : m# ≤ n# :=
53+ prod_le_prod_of_subset_of_one_le' (by gcongr) (by grind)
54+
55+ theorem primorial_monotone : Monotone primorial := fun _ _ ↦ primorial_mono
56+
57+ theorem primorial_dvd_primorial {m n : ℕ} (h : m ≤ n) : m# ∣ n# :=
58+ prod_dvd_prod_of_subset _ _ _ (by gcongr)
59+
4360theorem primorial_succ {n : ℕ} (hn1 : n ≠ 1 ) (hn : Odd n) : (n + 1 )# = n# := by
4461 refine prod_congr ?_ fun _ _ ↦ rfl
4562 rw [range_add_one, filter_insert, if_neg fun h ↦ not_even_iff_odd.2 hn _]
@@ -63,22 +80,58 @@ theorem primorial_add_dvd {m n : ℕ} (h : n ≤ m) : (m + n)# ∣ m# * choose (
6380theorem primorial_add_le {m n : ℕ} (h : n ≤ m) : (m + n)# ≤ m# * choose (m + n) m :=
6481 le_of_dvd (mul_pos (primorial_pos _) (choose_pos <| Nat.le_add_right _ _)) (primorial_add_dvd h)
6582
66- theorem primorial_le_4_pow (n : ℕ) : n# ≤ 4 ^ n := by
83+ lemma Nat.Prime.dvd_primorial_iff {p n : ℕ} (hp : Prime p) : p ∣ n# ↔ p ≤ n := by
84+ refine ⟨?_, fun h ↦ dvd_prod_of_mem _ (by grind)⟩
85+ intro h
86+ simp only [primorial, hp.prime.dvd_finset_prod_iff, mem_filter, mem_range_succ_iff] at h
87+ obtain ⟨q, ⟨hqn, hq⟩, hpq⟩ := h
88+ exact (Nat.le_of_dvd hq.pos hpq).trans hqn
89+
90+ lemma Nat.Prime.dvd_primorial {p : ℕ} (hp : Prime p) : p ∣ p# :=
91+ hp.dvd_primorial_iff.2 le_rfl
92+
93+ lemma Squarefree.dvd_primorial {n : ℕ} (hn : Squarefree n) : n ∣ n# := by
94+ have : (∏ p ∈ n.primeFactors, p) ∣ (∏ p ∈ range (n + 1 ) with p.Prime, p) :=
95+ Finset.prod_dvd_prod_of_subset _ _ _ (by grind [le_of_dvd])
96+ rwa [Nat.prod_primeFactors_of_squarefree hn] at this
97+
98+ lemma lt_primorial_self {n : ℕ} (hn : 2 < n) : n < n# := by
99+ have : 3 ≤ n# := single_le_prod' (f := id) (by grind [→ Prime.pos]) (by grind [prime_three])
100+ let q := (n# - 1 ).minFac
101+ have : n < q := by
102+ by_contra! h1
103+ replace h1 : q ∣ n# := (minFac_prime (by lia)).dvd_primorial_iff.2 h1
104+ grind [minFac_eq_one_iff, dvd_one, dvd_sub_iff_right, minFac_dvd]
105+ grind [Nat.minFac_le]
106+
107+ lemma le_primorial_self {n : ℕ} : n ≤ n# := by
108+ obtain hn | hn := le_or_gt n 2
109+ · decide +revert
110+ · exact (lt_primorial_self hn).le
111+
112+ theorem primorial_lt_four_pow (n : ℕ) (hn : n ≠ 0 ) : n# < 4 ^ n := by
67113 induction n using Nat.strong_induction_on with | h n ihn =>
68- rcases n with - | n; · rfl
69- rcases n.even_or_odd with ( ⟨m, rfl⟩ | ho)
70- · rcases m.eq_zero_or_pos with ( rfl | hm)
114+ rcases n with - | n; · grind
115+ rcases n.even_or_odd with ⟨m, rfl⟩ | ho
116+ · rcases m.eq_zero_or_pos with rfl | hm
71117 · decide
72118 calc
73119 (m + m + 1 )# = (m + 1 + m)# := by rw [add_right_comm]
74120 _ ≤ (m + 1 )# * choose (m + 1 + m) (m + 1 ) := primorial_add_le m.le_succ
75121 _ = (m + 1 )# * choose (2 * m + 1 ) m := by rw [choose_symm_add, two_mul, add_right_comm]
76- _ ≤ 4 ^ (m + 1 ) * 4 ^ m :=
77- mul_le_mul' (ihn _ <| succ_lt_succ <| (lt_add_iff_pos_left _). 2 hm ) (choose_middle_le_pow _)
122+ _ < 4 ^ (m + 1 ) * 4 ^ m :=
123+ Nat.mul_lt_mul_of_lt_of_le (ihn _ ( by lia) ( by lia) ) (choose_middle_le_pow _) ( by simp )
78124 _ ≤ 4 ^ (m + m + 1 ) := by rw [← pow_add, add_right_comm]
79- · rcases Decidable.eq_or_ne n 1 with ( rfl | hn)
125+ · rcases Decidable.eq_or_ne n 1 with rfl | hn
80126 · decide
81127 · calc
82128 (n + 1 )# = n# := primorial_succ hn ho
83- _ ≤ 4 ^ n := ihn n n.lt_succ_self
129+ _ < 4 ^ n := ihn n n.lt_succ_self ( by grind)
84130 _ ≤ 4 ^ (n + 1 ) := Nat.pow_le_pow_right four_pos n.le_succ
131+
132+ theorem primorial_le_four_pow (n : ℕ) : n# ≤ 4 ^ n := by
133+ obtain rfl | hn := eq_or_ne n 0
134+ · decide
135+ · exact (primorial_lt_four_pow n hn).le
136+
137+ @ [deprecated (since := "2026-03-21" )] alias primorial_le_4_pow := primorial_le_four_pow
0 commit comments