File: Mathlib/Data/Nat/Multiplicity.lean

full_name: Nat.multiplicity_eq_card_pow_dvd
code: /-- The multiplicity of `m` in `n` is the number of positive natural numbers `i` such that `m ^ i`
divides `n`. This set is expressed by filtering `Ico 1 b` where `b` is any bound greater than
`log m n`. -/
theorem multiplicity_eq_card_pow_dvd {m n b : ℕ} (hm : m ≠ 1) (hn : 0 < n) (hb : log m n < b) :
    multiplicity m n = ↑((Finset.Ico 1 b).filter fun i => m ^ i ∣ n).card 
goal: multiplicity m n = ↑(Finset.filter (fun i => m ^ i ∣ n) (Finset.Ico 1 b)).card

full_name: Nat.Prime.multiplicity_one
code: theorem multiplicity_one {p : ℕ} (hp : p.Prime) : multiplicity p 1 = 0 
goal: multiplicity p 1 = 0

full_name: Nat.Prime.multiplicity_mul
code: theorem multiplicity_mul {p m n : ℕ} (hp : p.Prime) :
    multiplicity p (m * n) = multiplicity p m + multiplicity p n 
goal: multiplicity p (m * n) = multiplicity p m + multiplicity p n

full_name: Nat.Prime.multiplicity_pow
code: theorem multiplicity_pow {p m n : ℕ} (hp : p.Prime) :
    multiplicity p (m ^ n) = n • multiplicity p m 
goal: multiplicity p (m ^ n) = n • multiplicity p m

full_name: Nat.Prime.multiplicity_self
code: theorem multiplicity_self {p : ℕ} (hp : p.Prime) : multiplicity p p = 1 
goal: multiplicity p p = 1

full_name: Nat.Prime.multiplicity_pow_self
code: theorem multiplicity_pow_self {p n : ℕ} (hp : p.Prime) : multiplicity p (p ^ n) = n 
goal: multiplicity p (p ^ n) = ↑n

full_name: Nat.Prime.multiplicity_factorial
code: /-- **Legendre's Theorem**

The multiplicity of a prime in `n!` is the sum of the quotients `n / p ^ i`. This sum is expressed
over the finset `Ico 1 b` where `b` is any bound greater than `log p n`. -/
theorem multiplicity_factorial {p : ℕ} (hp : p.Prime) :
    ∀ {n b : ℕ}, log p n < b → multiplicity p n ! = (∑ i ∈ Ico 1 b, n / p ^ i : ℕ)
  
goal: Nat.log p n < b → multiplicity p n ! = ↑(∑ i ∈ Finset.Ico 1 b, n / p ^ i)

full_name: Nat.Prime.sub_one_mul_multiplicity_factorial
code: /-- For a prime number `p`, taking `(p - 1)` times the multiplicity of `p` in `n!` equals `n` minus
the sum of base `p` digits of `n`. -/
 theorem sub_one_mul_multiplicity_factorial {n p : ℕ} (hp : p.Prime) :
     (p - 1) * (multiplicity p n !).get (finite_nat_iff.mpr ⟨hp.ne_one, factorial_pos n⟩) =
     n - (p.digits n).sum 
goal: (p - 1) * (multiplicity p n !).get ⋯ = n - (p.digits n).sum

full_name: Nat.Prime.multiplicity_factorial_mul_succ
code: /-- The multiplicity of `p` in `(p * (n + 1))!` is one more than the sum
  of the multiplicities of `p` in `(p * n)!` and `n + 1`. -/
theorem multiplicity_factorial_mul_succ {n p : ℕ} (hp : p.Prime) :
    multiplicity p (p * (n + 1))! = multiplicity p (p * n)! + multiplicity p (n + 1) + 1 
goal: multiplicity p (p * (n + 1))! = multiplicity p (p * n)! + multiplicity p (n + 1) + 1

full_name: Nat.Prime.multiplicity_factorial_mul
code: /-- The multiplicity of `p` in `(p * n)!` is `n` more than that of `n!`. -/
theorem multiplicity_factorial_mul {n p : ℕ} (hp : p.Prime) :
    multiplicity p (p * n)! = multiplicity p n ! + n 
goal: multiplicity p (p * n)! = multiplicity p n ! + ↑n

full_name: Nat.Prime.pow_dvd_factorial_iff
code: /-- A prime power divides `n!` iff it is at most the sum of the quotients `n / p ^ i`.
  This sum is expressed over the set `Ico 1 b` where `b` is any bound greater than `log p n` -/
theorem pow_dvd_factorial_iff {p : ℕ} {n r b : ℕ} (hp : p.Prime) (hbn : log p n < b) :
    p ^ r ∣ n ! ↔ r ≤ ∑ i ∈ Ico 1 b, n / p ^ i 
goal: p ^ r ∣ n ! ↔ r ≤ ∑ i ∈ Finset.Ico 1 b, n / p ^ i

full_name: Nat.Prime.multiplicity_factorial_le_div_pred
code: theorem multiplicity_factorial_le_div_pred {p : ℕ} (hp : p.Prime) (n : ℕ) :
    multiplicity p n ! ≤ (n / (p - 1) : ℕ) 
goal: multiplicity p n ! ≤ ↑(n / (p - 1))

full_name: Nat.Prime.multiplicity_choose_aux
code: theorem multiplicity_choose_aux {p n b k : ℕ} (hp : p.Prime) (hkn : k ≤ n) :
    ∑ i ∈ Finset.Ico 1 b, n / p ^ i =
      ((∑ i ∈ Finset.Ico 1 b, k / p ^ i) + ∑ i ∈ Finset.Ico 1 b, (n - k) / p ^ i) +
        ((Finset.Ico 1 b).filter fun i => p ^ i ≤ k % p ^ i + (n - k) % p ^ i).card 
goal: ∑ i ∈ Finset.Ico 1 b, n / p ^ i =
  ∑ i ∈ Finset.Ico 1 b, k / p ^ i + ∑ i ∈ Finset.Ico 1 b, (n - k) / p ^ i +
    (Finset.filter (fun i => p ^ i ≤ k % p ^ i + (n - k) % p ^ i) (Finset.Ico 1 b)).card

full_name: Nat.Prime.multiplicity_choose'
code: /-- The multiplicity of `p` in `choose (n + k) k` is the number of carries when `k` and `n`
  are added in base `p`. The set is expressed by filtering `Ico 1 b` where `b`
  is any bound greater than `log p (n + k)`. -/
theorem multiplicity_choose' {p n k b : ℕ} (hp : p.Prime) (hnb : log p (n + k) < b) :
    multiplicity p (choose (n + k) k) =
      ((Ico 1 b).filter fun i => p ^ i ≤ k % p ^ i + n % p ^ i).card 
goal: multiplicity p ((n + k).choose k) = ↑(Finset.filter (fun i => p ^ i ≤ k % p ^ i + n % p ^ i) (Finset.Ico 1 b)).card

full_name: Nat.Prime.multiplicity_choose
code: /-- The multiplicity of `p` in `choose n k` is the number of carries when `k` and `n - k`
  are added in base `p`. The set is expressed by filtering `Ico 1 b` where `b`
  is any bound greater than `log p n`. -/
theorem multiplicity_choose {p n k b : ℕ} (hp : p.Prime) (hkn : k ≤ n) (hnb : log p n < b) :
    multiplicity p (choose n k) =
      ((Ico 1 b).filter fun i => p ^ i ≤ k % p ^ i + (n - k) % p ^ i).card 
goal: multiplicity p (n.choose k) = ↑(Finset.filter (fun i => p ^ i ≤ k % p ^ i + (n - k) % p ^ i) (Finset.Ico 1 b)).card

full_name: Nat.Prime.multiplicity_le_multiplicity_choose_add
code: /-- A lower bound on the multiplicity of `p` in `choose n k`. -/
theorem multiplicity_le_multiplicity_choose_add {p : ℕ} (hp : p.Prime) :
    ∀ n k : ℕ, multiplicity p n ≤ multiplicity p (choose n k) + multiplicity p k
  
goal: multiplicity p n ≤ multiplicity p (n.choose k) + multiplicity p k

full_name: Nat.Prime.multiplicity_choose_prime_pow_add_multiplicity
code: theorem multiplicity_choose_prime_pow_add_multiplicity (hp : p.Prime) (hkn : k ≤ p ^ n)
    (hk0 : k ≠ 0) : multiplicity p (choose (p ^ n) k) + multiplicity p k = n 
goal: multiplicity p ((p ^ n).choose k) + multiplicity p k = ↑n

full_name: Nat.Prime.multiplicity_choose_prime_pow
code: theorem multiplicity_choose_prime_pow {p n k : ℕ} (hp : p.Prime) (hkn : k ≤ p ^ n) (hk0 : k ≠ 0) :
    multiplicity p (choose (p ^ n) k) =
      ↑(n - (multiplicity p k).get (finite_nat_iff.2 ⟨hp.ne_one, hk0.bot_lt⟩)) 
goal: multiplicity p ((p ^ n).choose k) = ↑(n - (multiplicity p k).get ⋯)

full_name: Nat.Prime.dvd_choose_pow
code: theorem dvd_choose_pow (hp : Prime p) (hk : k ≠ 0) (hkp : k ≠ p ^ n) : p ∣ (p ^ n).choose k 
goal: p ∣ (p ^ n).choose k

full_name: Nat.Prime.dvd_choose_pow_iff
code: theorem dvd_choose_pow_iff (hp : Prime p) : p ∣ (p ^ n).choose k ↔ k ≠ 0 ∧ k ≠ p ^ n 
goal: p ∣ (p ^ n).choose k ↔ k ≠ 0 ∧ k ≠ p ^ n

full_name: Nat.multiplicity_two_factorial_lt
code: theorem multiplicity_two_factorial_lt : ∀ {n : ℕ} (_ : n ≠ 0), multiplicity 2 n ! < n 
goal: n ≠ 0 → multiplicity 2 n ! < ↑n