/-- **Faulhaber's theorem** relating the **sum of p-th powers** to the Bernoulli numbers:
$$\sum_{k=0}^{n-1} k^p = \sum_{i=0}^p B_i\binom{p+1}{i}\frac{n^{p+1-i}}{p+1}.$$
See https://proofwiki.org/wiki/Faulhaber%27s_Formula and [orosi2018faulhaber] for
the proof provided here. -/
theorem sum_range_pow (n p : ℕ) :
    (∑ k in range n, (k : ℚ) ^ p) =
      ∑ i in range (p + 1), bernoulli i * ((p + 1).choose i) * (n : ℚ) ^ (p + 1 - i) / (p + 1) := by
  have hne : ∀ m : ℕ, (m ! : ℚ) ≠ 0 := fun m => mod_cast factorial_ne_zero m
  -- compute the Cauchy product of two power series
  have h_cauchy :
    ((mk fun p => bernoulli p / p !) * mk fun q => coeff ℚ (q + 1) (exp ℚ ^ n)) =
      mk fun p => ∑ i in range (p + 1),
          bernoulli i * (p + 1).choose i * (n : ℚ) ^ (p + 1 - i) / (p + 1)! := by
    ext q : 1
    let f a b := bernoulli a / a ! * coeff ℚ (b + 1) (exp ℚ ^ n)
    -- key step: use `PowerSeries.coeff_mul` and then rewrite sums
    simp only [coeff_mul, coeff_mk, cast_mul, sum_antidiagonal_eq_sum_range_succ f]
    apply sum_congr rfl
    intros m h
    simp only [exp_pow_eq_rescale_exp, rescale, one_div, coeff_mk, RingHom.coe_mk, coeff_exp,
      RingHom.id_apply, cast_mul, algebraMap_rat_rat]
    -- manipulate factorials and binomial coefficients
    simp? at h says simp only [mem_range] at h
    rw [choose_eq_factorial_div_factorial h.le, eq_comm, div_eq_iff (hne q.succ), succ_eq_add_one,
      mul_assoc _ _ (q.succ ! : ℚ), mul_comm _ (q.succ ! : ℚ), ← mul_assoc, div_mul_eq_mul_div]
    

Proof state:
case h
A : Type u_1
inst✝¹ : CommRing A
inst✝ : Algebra ℚ A
n p : ℕ
hne : ∀ (m : ℕ), ↑m ! ≠ 0
q : ℕ
f : ℕ → ℕ → ℚ := fun a b => bernoulli a / ↑a ! * (coeff ℚ (b + 1)) (exp ℚ ^ n)
m : ℕ
h : m < succ q
⊢ bernoulli m * ↑((q + 1)! / (m ! * (q + 1 - m)!)) * ↑n ^ (q + 1 - m) =
    bernoulli m * ↑(succ q)! / ↑m ! *
      (coeff ℚ (q - m + 1))
        ({
            toOneHom :=
              { toFun := fun f => PowerSeries.mk fun n_1 => ↑n ^ n_1 * (coeff ℚ n_1) f,
                map_one' := (_ : (fun f => PowerSeries.mk fun n_1 => ↑n ^ n_1 * (coeff ℚ n_1) f) 1 = 1) },
            map_mul' :=
              (_ :
                ∀ (f g : ℚ⟦X⟧),
                  OneHom.toFun
                      { toFun := fun f => PowerSeries.mk fun n_1 => ↑n ^ n_1 * (coeff ℚ n_1) f,
                        map_one' := (_ : (fun f => PowerSeries.mk fun n_1 => ↑n ^ n_1 * (coeff ℚ n_1) f) 1 = 1) }
                      (f * g) =
                    OneHom.toFun
                        { toFun := fun f => PowerSeries.mk fun n_1 => ↑n ^ n_1 * (coeff ℚ n_1) f,
                          map_one' := (_ : (fun f => PowerSeries.mk fun n_1 => ↑n ^ n_1 * (coeff ℚ n_1) f) 1 = 1) }
                        f *
                      OneHom.toFun
                        { toFun := fun f => PowerSeries.mk fun n_1 => ↑n ^ n_1 * (coeff ℚ n_1) f,
                          map_one' := (_ : (fun f => PowerSeries.mk fun n_1 => ↑n ^ n_1 * (coeff ℚ n_1) f) 1 = 1) }
                        g) }
          (exp ℚ))

Next tactic:
simp only [add_eq, add_zero, ge_iff_le, IsUnit.mul_iff, Nat.isUnit_iff, succ.injEq, cast_mul,
      cast_succ, MonoidHom.coe_mk, OneHom.coe_mk, coeff_exp, Algebra.id.map_eq_id, one_div,
      map_inv₀, map_natCast, coeff_mk, mul_inv_rev]