88public import Mathlib.Algebra.CharP.Lemmas
99public import Mathlib.Data.ZMod.Basic
1010public import Mathlib.RingTheory.Polynomial.Basic
11+ meta import Mathlib.Tactic.GRewrite
1112
1213/-!
1314# Lucas's theorem
@@ -31,7 +32,7 @@ open Nat Polynomial
3132
3233namespace Choose
3334
34- variable {n k p : ℕ} [Fact p.Prime]
35+ variable {n k a b p : ℕ} [Fact p.Prime]
3536
3637/-- For primes `p`, `choose n k` is congruent to `choose (n % p) (k % p) * choose (n / p) (k / p)`
3738modulo `p`. Also see `choose_modEq_choose_mod_mul_choose_div_nat` for the version with `MOD`. -/
@@ -101,4 +102,34 @@ theorem choose_modEq_prod_range_choose_nat {a : ℕ} (ha₁ : n < p ^ a) (ha₂
101102alias lucas_theorem := choose_modEq_prod_range_choose
102103alias lucas_theorem_nat := choose_modEq_prod_range_choose_nat
103104
105+ /-- For primes `p`, `choose (p * a) (p * b)` is congruent to `choose a b` modulo `p`.
106+ Also see `choose_mul_mul_modEq_choose_nat` for the version with `MOD`. -/
107+ theorem choose_mul_mul_modEq_choose :
108+ choose (p * a) (p * b) ≡ choose a b [ZMOD p] := by
109+ grw [choose_modEq_choose_mod_mul_choose_div]
110+ simp [NeZero.pos, Int.ModEq.refl]
111+
112+ /-- For primes `p`, `choose (p * a) (p * b)` is congruent to `choose a b` modulo `p`.
113+ Also see `choose_mul_mul_modEq_choose` for the version with `ZMOD`. -/
114+ theorem choose_mul_mul_modEq_choose_nat :
115+ choose (p * a) (p * b) ≡ choose a b [MOD p] := by
116+ rw [← Int.natCast_modEq_iff]
117+ exact_mod_cast choose_mul_mul_modEq_choose
118+
119+ /-- For primes `p`, `choose (p ^ k * a) (p ^ k * b)` is congruent to `choose a b` modulo `p`.
120+ Also see `choose_pow_mul_pow_mul_modEq_choose_nat` for the version with `MOD`. -/
121+ theorem choose_pow_mul_pow_mul_modEq_choose :
122+ choose (p ^ k * a) (p ^ k * b) ≡ choose a b [ZMOD p] := by
123+ induction k with
124+ | zero => simp [Int.ModEq.refl]
125+ | succ k ih =>
126+ grw [Nat.pow_succ', mul_assoc, mul_assoc, choose_mul_mul_modEq_choose, ih]
127+
128+ /-- For primes `p`, `choose (p ^ k * a) (p ^ k * b)` is congruent to `choose a b` modulo `p`.
129+ Also see `choose_pow_mul_pow_mul_modEq_choose` for the version with `ZMOD`. -/
130+ theorem choose_pow_mul_pow_mul_modEq_choose_nat :
131+ choose (p ^ k * a) (p ^ k * b) ≡ choose a b [MOD p] := by
132+ rw [← Int.natCast_modEq_iff]
133+ exact_mod_cast choose_pow_mul_pow_mul_modEq_choose
134+
104135end Choose
0 commit comments