Skip to content

Commit b764b11

Browse files
committed
feat(Data/Nat/Choose/Lucas): add choose_mul_mul and choose_pow_mul_pow_mul modular congruence lemmas (leanprover-community#35893)
1 parent 89758f0 commit b764b11

File tree

1 file changed

+32
-1
lines changed

1 file changed

+32
-1
lines changed

Mathlib/Data/Nat/Choose/Lucas.lean

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ module
88
public import Mathlib.Algebra.CharP.Lemmas
99
public import Mathlib.Data.ZMod.Basic
1010
public 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

3233
namespace 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)`
3738
modulo `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₂
101102
alias lucas_theorem := choose_modEq_prod_range_choose
102103
alias 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+
104135
end Choose

0 commit comments

Comments
 (0)