Skip to content

Commit d6772ec

Browse files
committed
feat(Data/Nat): a number divides a power of its own radical (#40170)
A few factorization lemmas, including: - `∀ n : ℕ`, `n ∣ radical n ^ n` - `∀ n k : ℕ`, `n ∣ k ^ n ↔ n.primeFactors ⊆ k.primeFactors` - `∀ n k : ℕ`, `radical n ∣ k ↔ n.primeFactors ⊆ k.primeFactors` - In any `UniqueFactorizationMonoid M`, `∀ a : M`, `∃ n, a ∣ radical a ^ n` [#Is there code for X? > A number divides a power of its square-free component](https://leanprover.zulipchat.com/#narrow/channel/217875-Is-there-code-for-X.3F/topic/A.20number.20divides.20a.20power.20of.20its.20square-free.20component/with/599339469)
1 parent 24434ef commit d6772ec

8 files changed

Lines changed: 102 additions & 18 deletions

File tree

Mathlib/Algebra/Order/Group/Multiset.lean

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,12 @@ lemma mem_nsmul {a : α} {s : Multiset α} {n : ℕ} : a ∈ n • s ↔ n ≠ 0
6363
lemma mem_nsmul_of_ne_zero {a : α} {s : Multiset α} {n : ℕ} (h0 : n ≠ 0) : a ∈ n • s ↔ a ∈ s := by
6464
simp [*]
6565

66+
theorem smul_subset_self (s : Multiset α) (n : ℕ) : n • s ⊆ s :=
67+
subset_iff.mpr fun _ ↦ mem_of_mem_nsmul
68+
69+
theorem subset_smul_self_of_ne_zero (s : Multiset α) {n : ℕ} (hn : n ≠ 0) : s ⊆ n • s :=
70+
subset_iff.mpr fun _ ↦ mem_nsmul_of_ne_zero hn |>.mpr
71+
6672
lemma nsmul_cons {s : Multiset α} (n : ℕ) (a : α) :
6773
n • (a ::ₘ s) = n • ({a} : Multiset α) + n • s := by
6874
rw [← singleton_add, nsmul_add]
@@ -180,6 +186,14 @@ lemma count_nsmul (a : α) (n s) : count a (n • s) = n * count a s := by
180186

181187
end
182188

189+
theorem le_card_smul_iff_subset {s t : Multiset α} : s ≤ s.card • t ↔ s ⊆ t := by
190+
classical
191+
refine ⟨fun hle ↦ Subset.trans (subset_of_le hle) (t.smul_subset_self s.card), ?_⟩
192+
refine fun hsub ↦ le_iff_count.mpr fun a ↦ ?_
193+
by_cases! has : a ∉ s
194+
· simp [count_eq_zero_of_notMem has]
195+
grw [count_le_card, count_nsmul, ← one_le_count_iff_mem.mpr <| mem_of_subset hsub has, mul_one]
196+
183197
-- TODO: This should be `addMonoidHom_ext`
184198
@[ext]
185199
lemma addHom_ext [AddZeroClass β] ⦃f g : Multiset α →+ β⦄ (h : ∀ x, f {x} = g {x}) : f = g := by
@@ -189,14 +203,6 @@ lemma addHom_ext [AddZeroClass β] ⦃f g : Multiset α →+ β⦄ (h : ∀ x, f
189203
| cons a s ih => simp only [← singleton_add, _root_.map_add, ih, h]
190204

191205
theorem le_smul_dedup [DecidableEq α] (s : Multiset α) : ∃ n : ℕ, s ≤ n • dedup s :=
192-
⟨(s.map fun a => count a s).fold max 0,
193-
le_iff_count.2 fun a => by
194-
rw [count_nsmul]; by_cases h : a ∈ s
195-
· grw [← one_le_count_iff_mem.2 <| mem_dedup.2 h]
196-
have : count a s ≤ fold max 0 (map (fun a => count a s) (a ::ₘ erase s a)) := by
197-
simp
198-
rw [cons_erase h] at this
199-
simpa [mul_succ] using this
200-
· simp [count_eq_zero.2 h, Nat.zero_le]⟩
206+
⟨s.card, le_card_smul_iff_subset.mpr s.subset_dedup⟩
201207

202208
end Multiset

Mathlib/Data/Nat/Choose/Lucas.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ theorem gcd_choose_eq_minFac_of_isPrimePow (h : IsPrimePow n) :
208208
have : multiplicity n.minFac ((Icc 1 (n - 1)).gcd n.choose) = 1 := by
209209
refine multiplicity_eq_of_dvd_of_not_dvd ?_ (minFac_sq_ndvd_gcd_choose_of_isPrimePow h)
210210
simpa using minFac_dvd_gcd_choose_of_isPrimePow h
211-
rw [Nat.prod_pow_primeFactors_factorization ne_zero, primeFactors_gcd_choose_of_isPrimePow h]
211+
rw [Nat.prod_primeFactors_coe_pow_factorization ne_zero, primeFactors_gcd_choose_of_isPrimePow h]
212212
simp [← Nat.multiplicity_eq_factorization isPrime ne_zero, this]
213213

214214
/-- For a natural number `n` greater than `1`, assume that `n` is not a prime power, then

Mathlib/Data/Nat/Factorization/Basic.lean

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -477,11 +477,16 @@ theorem prod_pow_prime_padicValNat (n : Nat) (hn : n ≠ 0) (m : Nat) (pr : n <
477477
· intro p hp
478478
simp [factorization_def n (prime_of_mem_primeFactors hp)]
479479

480-
lemma prod_pow_primeFactors_factorization (hn : n ≠ 0) :
480+
theorem prod_primeFactors_pow_factorization (hn : n ≠ 0) :
481+
n = ∏ p ∈ n.primeFactors, p ^ n.factorization p :=
482+
prod_factorization_pow_eq_self hn |>.symm.trans <| prod_factorization_eq_prod_primeFactors _
483+
484+
lemma prod_primeFactors_coe_pow_factorization (hn : n ≠ 0) :
481485
n = ∏ (p : n.primeFactors), (p : ℕ) ^ (n.factorization p) := by
482-
nth_rw 1 [← prod_factorization_pow_eq_self hn]
483-
rw [prod_factorization_eq_prod_primeFactors _]
484-
exact prod_subtype n.primeFactors (fun _ ↦ Iff.rfl) fun a ↦ a ^ n.factorization a
486+
simpa using prod_primeFactors_pow_factorization hn
487+
488+
@[deprecated (since := "2026-06-24")]
489+
alias prod_pow_primeFactors_factorization := prod_primeFactors_coe_pow_factorization
485490

486491
lemma pairwise_coprime_pow_primeFactors_factorization :
487492
Pairwise (Function.onFun Nat.Coprime fun (p : n.primeFactors) ↦ p ^ n.factorization p) := by
@@ -491,6 +496,26 @@ lemma pairwise_coprime_pow_primeFactors_factorization :
491496
· exact Nat.prime_of_mem_primeFactors p1.2
492497
· exact Nat.prime_of_mem_primeFactors p2.2
493498

499+
theorem dvd_prod_primeFactors_pow_self {n : ℕ} (hn : n ≠ 0) :
500+
n ∣ (∏ p ∈ n.primeFactors, p) ^ n := by
501+
nth_rw 1 [← Finset.prod_pow, prod_primeFactors_pow_factorization hn]
502+
refine prod_dvd_prod_of_dvd _ _ fun i hi ↦ pow_dvd_pow i ?_
503+
grw [n.factorization_def <| prime_of_mem_primeFactors hi, padicValNat_le_self]
504+
505+
theorem dvd_pow_self_iff {n k : ℕ} (hn : n ≠ 0) (hk : k ≠ 0) :
506+
n ∣ k ^ n ↔ n.primeFactors ⊆ k.primeFactors := by
507+
refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
508+
· grw [← Nat.primeFactors_pow k hn, Nat.primeFactors_mono h <| pow_ne_zero n hk]
509+
· grw [dvd_prod_primeFactors_pow_self hn, prod_dvd_prod_of_subset _ _ _ h, prod_primeFactors_dvd]
510+
511+
theorem exists_dvd_pow_iff {n k : ℕ} (hn : n ≠ 0) (hk : k ≠ 0) :
512+
(∃ m, n ∣ k ^ m) ↔ n.primeFactors ⊆ k.primeFactors := by
513+
refine ⟨fun ⟨m, h⟩ ↦ ?_, fun h ↦ ⟨n, dvd_pow_self_iff hn hk |>.mpr h⟩⟩
514+
rcases eq_or_ne m 0 with (rfl | hm)
515+
· simp_all
516+
rw [← Nat.primeFactors_pow k hm]
517+
exact Nat.primeFactors_mono h <| pow_ne_zero m hk
518+
494519
/-! ### Lemmas about factorizations of particular functions -/
495520

496521
/-- Exactly `n / p` naturals in `[1, n]` are multiples of `p`.

Mathlib/Data/Nat/MaxPowDiv.lean

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,19 @@ theorem pow_padicValNat_mul_divMaxPow (p n : ℕ) : p ^ padicValNat p n * divMax
136136
theorem _root_.pow_padicValNat_dvd {p n : ℕ} : p ^ padicValNat p n ∣ n :=
137137
⟨divMaxPow n p, by simp⟩
138138

139+
theorem padicValNat_lt_self {p n : ℕ} (hn : n ≠ 0) : padicValNat p n < n := by
140+
match p with
141+
| 0 | 1 => simp [Nat.pos_of_ne_zero hn]
142+
| p + 2 =>
143+
apply (p + 2 |>.pow_lt_pow_iff_right <| by lia).mp
144+
apply Nat.lt_of_le_of_lt ?_ <| Nat.lt_pow_self <| by lia
145+
exact le_of_dvd (Nat.pos_of_ne_zero hn) pow_padicValNat_dvd
146+
147+
theorem padicValNat_le_self {p : ℕ} (n : ℕ) : padicValNat p n ≤ n := by
148+
rcases eq_or_ne n 0 with rfl | hn
149+
· simp
150+
· exact Nat.le_of_lt <| padicValNat_lt_self hn
151+
139152
theorem not_dvd_divMaxPow {p n : ℕ} (hp : 1 < p) (hn : n ≠ 0) : ¬p ∣ divMaxPow n p := by
140153
simp [divMaxPow, maxPowDvdDiv, maxPowDvdDiv.go_spec, *]
141154

Mathlib/Data/Nat/Squarefree.lean

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,16 @@ lemma primeFactors_prod (hs : ∀ p ∈ s, p.Prime) : primeFactors (∏ p ∈ s,
373373
rintro ⟨hp, q, hq, hpq⟩
374374
rwa [← ((hs _ hq).dvd_iff_eq hp.ne_one).1 hpq]
375375

376+
theorem primeFactors_prod_primeFactors (n : ℕ) :
377+
(∏ p ∈ n.primeFactors, p).primeFactors = n.primeFactors :=
378+
primeFactors_prod fun _ hp ↦ n.mem_primeFactors.mp hp |>.left
379+
380+
theorem prod_primeFactors_dvd_iff {n k : ℕ} (hk : k ≠ 0) :
381+
(∏ p ∈ n.primeFactors, p) ∣ k ↔ n.primeFactors ⊆ k.primeFactors := by
382+
refine ⟨fun h ↦ ?_, fun h ↦ ?_⟩
383+
· grw [← Nat.primeFactors_mono h hk, primeFactors_prod_primeFactors]
384+
· grw [← k.prod_primeFactors_dvd, Finset.prod_dvd_prod_of_subset _ _ _ h]
385+
376386
lemma primeFactors_div_gcd (hm : Squarefree m) (hn : n ≠ 0) :
377387
primeFactors (m / m.gcd n) = primeFactors m \ primeFactors n := by
378388
ext p

Mathlib/Data/ZMod/QuotientRing.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ def ZMod.prodEquivPi {ι : Type*} [Fintype ι] (a : ι → ℕ)
8787
/-- The **Chinese remainder theorem**, version for `ZMod n`. -/
8888
def ZMod.equivPi (hn : n ≠ 0) :
8989
ZMod n ≃+* Π (p : n.primeFactors), ZMod (p ^ (n.factorization p)) :=
90-
(ringEquivCongr <| Nat.prod_pow_primeFactors_factorization hn).trans
90+
(ringEquivCongr <| Nat.prod_primeFactors_coe_pow_factorization hn).trans
9191
<| prodEquivPi (fun (p : n.primeFactors) ↦ (p : ℕ) ^ (n.factorization p))
9292
n.pairwise_coprime_pow_primeFactors_factorization
9393

Mathlib/RingTheory/Radical/Basic.lean

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ open scoped Classical in
5656
def primeFactors (a : M) : Finset M :=
5757
(normalizedFactors a).toFinset
5858

59+
@[simp]
60+
theorem toFinset_normalizedFactors [DecidableEq M] :
61+
(normalizedFactors a).toFinset = primeFactors a := by
62+
unfold primeFactors
63+
convert rfl
64+
5965
lemma mem_primeFactors : a ∈ primeFactors b ↔ a ∈ normalizedFactors b := by
6066
simp only [primeFactors, Multiset.mem_toFinset]
6167

@@ -296,6 +302,22 @@ theorem radical_dvd_iff_primeFactors_subset (hb : b ≠ 0) :
296302
rw [← dvd_radical_iff isRadical_radical hb,
297303
radical_dvd_radical_iff_primeFactors_subset_primeFactors]
298304

305+
theorem exists_dvd_pow_iff_radical_dvd (ha : a ≠ 0) : (∃ n, a ∣ b ^ n) ↔ radical a ∣ b := by
306+
rcases eq_or_ne b 0 with (rfl | hb)
307+
· exact ⟨by simp, fun _ ↦ ⟨1, by simp⟩⟩
308+
refine ⟨fun ⟨n, hdvd⟩ ↦ ?_, fun h ↦ ⟨normalizedFactors a |>.card, ?_⟩⟩
309+
· rcases eq_or_ne n 0 with (rfl | hn)
310+
· simp [radical_of_isUnit <| isUnit_of_dvd_one <| pow_zero b ▸ hdvd]
311+
grw [radical_dvd_radical hdvd <| pow_ne_zero _ hb, radical_pow b hn, radical_dvd_self]
312+
· classical
313+
rwa [dvd_iff_normalizedFactors_le_normalizedFactors ha <| pow_ne_zero _ hb,
314+
normalizedFactors_pow, Multiset.le_card_smul_iff_subset, ← Multiset.toFinset_subset,
315+
toFinset_normalizedFactors, toFinset_normalizedFactors,
316+
← radical_dvd_iff_primeFactors_subset hb]
317+
318+
theorem exists_dvd_radical_self_pow (ha : a ≠ 0) : ∃ n, a ∣ radical a ^ n := by
319+
rw [exists_dvd_pow_iff_radical_dvd ha]
320+
299321
/-- Radical is multiplicative for relatively prime elements. -/
300322
theorem radical_mul (hc : IsRelPrime a b) :
301323
radical (a * b) = radical a * radical b := by

Mathlib/RingTheory/Radical/NatInt.lean

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@ Authors: Bhavik Mehta, Arend Mellendijk, Jeremy Tan
66
module
77

88
public import Mathlib.Algebra.EuclideanDomain.Int
9-
public import Mathlib.Algebra.GCDMonoid.Nat
109
public import Mathlib.Data.Nat.Prime.Int
11-
public import Mathlib.Data.Nat.PrimeFin
10+
public import Mathlib.Data.Nat.Squarefree
1211
public import Mathlib.RingTheory.PrincipalIdealDomain
1312
public import Mathlib.RingTheory.Radical.Basic
14-
public import Mathlib.RingTheory.UniqueFactorizationDomain.Nat
1513

1614
/-!
1715
# The radical in `ℕ` and `ℤ`
@@ -73,6 +71,16 @@ lemma radical_pos (n) : 0 < radical n := pos_of_ne_zero radical_ne_zero
7371
@[simp] lemma self_lt_radical_iff : n < radical n ↔ n = 0 := by
7472
simpa only [not_le, not_not] using radical_le_self_iff.not
7573

74+
theorem primeFactors_radical (n : ℕ) : (radical n).primeFactors = n.primeFactors := by
75+
rw [radical_eq_prod_primeFactors, primeFactors_prod_primeFactors]
76+
77+
theorem radical_dvd_iff {n k : ℕ} (hk : k ≠ 0) :
78+
radical n ∣ k ↔ n.primeFactors ⊆ k.primeFactors := by
79+
rw [radical_eq_prod_primeFactors, prod_primeFactors_dvd_iff hk]
80+
81+
theorem dvd_radical_pow_self {n : ℕ} (hn : n ≠ 0) : n ∣ radical n ^ n := by
82+
grw [radical_eq_prod_primeFactors, ← dvd_prod_primeFactors_pow_self hn]
83+
7684
open Qq Lean Mathlib.Meta Finset
7785

7886
namespace Mathlib.Meta.Positivity

0 commit comments

Comments
 (0)