l3lab/ntp-mathlib huggingface dataset:
/-- Construction of a group with commuting probability `1 / n`. -/
theorem commProb_reciprocal (n : ℕ) :
    commProb (Product (reciprocalFactors n)) = 1 / n := by
  by_cases h0 : n = 0
  · rw [h0, reciprocalFactors_zero, commProb_cons, commProb_nil, mul_one, Nat.cast_zero, div_zero]
    apply commProb_eq_zero_of_infinite
  by_cases h1 : n = 1
  · rw [h1, reciprocalFactors_one, commProb_nil, Nat.cast_one, div_one]
  rcases Nat.even_or_odd n with h2 | h2
  · have := div_two_lt h0
    rw [reciprocalFactors_even h0 h2, commProb_cons, commProb_reciprocal (n / 2),
        commProb_odd (by decide)]
    field_simp [h0, h2.two_dvd]
    norm_num
  · have := div_four_lt h0 h1
    rw [reciprocalFactors_odd h1 h2, commProb_cons, commProb_reciprocal (n / 4 + 1)]
    have key : n % 4 = 1 ∨ n % 4 = 3 := Nat.odd_mod_four_iff.mp (Nat.odd_iff.mp h2)
    have hn : Odd (n % 4) := by rcases key with h | h <;> rw [h] <;> decide
    rw [commProb_odd (hn.mul h2), div_mul_div_comm, mul_one, div_eq_div_iff, one_mul] <;> norm_cast
    · have h0 : (n % 4) ^ 2 + 3 = n % 4 * 4 := by rcases key with h | h <;> rw [h] <;> norm_num
      have h1 := (Nat.div_add_mod n 4).symm
      zify at h0 h1 ⊢
      linear_combination (h0 + h1 * (n % 4)) * n
    · 

Proof state:
case neg.inr.hb
M : Type u_1
inst✝³ : Mul M
inst✝² : Finite M
G : Type u_2
inst✝¹ : Group G
inst✝ : Finite G
H : Subgroup G
n : ℕ
h0 : ¬n = 0
h1 : ¬n = 1
h2 : Odd n
this : n / 4 + 1 < n
key : n % 4 = 1 ∨ n % 4 = 3
hn : Odd (n % 4)
⊢ ¬4 * (n % 4 * n) * (n / 4 + 1) = 0

Next tactic:
have := hn.pos.ne'
/-- Construction of a group with commuting probability `1 / n`. -/
theorem commProb_reciprocal (n : ℕ) :
    commProb (Product (reciprocalFactors n)) = 1 / n := by
  by_cases h0 : n = 0
  · rw [h0, reciprocalFactors_zero, commProb_cons, commProb_nil, mul_one, Nat.cast_zero, div_zero]
    apply commProb_eq_zero_of_infinite
  by_cases h1 : n = 1
  · rw [h1, reciprocalFactors_one, commProb_nil, Nat.cast_one, div_one]
  rcases Nat.even_or_odd n with h2 | h2
  · have := div_two_lt h0
    rw [reciprocalFactors_even h0 h2, commProb_cons, commProb_reciprocal (n / 2),
        commProb_odd (by decide)]
    field_simp [h0, h2.two_dvd]
    norm_num
  · have := div_four_lt h0 h1
    rw [reciprocalFactors_odd h1 h2, commProb_cons, commProb_reciprocal (n / 4 + 1)]
    have key : n % 4 = 1 ∨ n % 4 = 3 := Nat.odd_mod_four_iff.mp (Nat.odd_iff.mp h2)
    have hn : Odd (n % 4) := by rcases key with h | h <;> rw [h] <;> decide
    rw [commProb_odd (hn.mul h2), div_mul_div_comm, mul_one, div_eq_div_iff, one_mul] <;> norm_cast
    · have h0 : (n % 4) ^ 2 + 3 = n % 4 * 4 := by rcases key with h | h <;> rw [h] <;> norm_num
      have h1 := (Nat.div_add_mod n 4).symm
      zify at h0 h1 ⊢
      linear_combination (h0 + h1 * (n % 4)) * n
    · have := hn.pos.ne'
      

Proof state:
case neg.inr.hb
M : Type u_1
inst✝³ : Mul M
inst✝² : Finite M
G : Type u_2
inst✝¹ : Group G
inst✝ : Finite G
H : Subgroup G
n : ℕ
h0 : ¬n = 0
h1 : ¬n = 1
h2 : Odd n
this✝ : n / 4 + 1 < n
key : n % 4 = 1 ∨ n % 4 = 3
hn : Odd (n % 4)
this : n % 4 ≠ 0
⊢ ¬4 * (n % 4 * n) * (n / 4 + 1) = 0

Next tactic:
positivity
@[qify_simps] lemma int_cast_eq (a b : ℤ) : a = b ↔ (a : ℚ) = (b : ℚ) := by 

Proof state:
a b : ℤ
⊢ a = b ↔ ↑a = ↑b

Next tactic:
simp only [Int.cast_inj]
@[qify_simps] lemma int_cast_ne (a b : ℤ) : a ≠ b ↔ (a : ℚ) ≠ (b : ℚ) := by
  

Proof state:
a b : ℤ
⊢ a ≠ b ↔ ↑a ≠ ↑b

Next tactic:
simp only [ne_eq, Int.cast_inj]
theorem wittPolyProd_vars (n : ℕ) : (wittPolyProd p n).vars ⊆ univ ×ˢ range (n + 1) := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (wittPolyProd p n) ⊆ univ ×ˢ range (n + 1)

Next tactic:
rw [wittPolyProd]
theorem wittPolyProd_vars (n : ℕ) : (wittPolyProd p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [wittPolyProd]
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars ((rename (Prod.mk 0)) (wittPolynomial p ℤ n) * (rename (Prod.mk 1)) (wittPolynomial p ℤ n)) ⊆
    univ ×ˢ range (n + 1)

Next tactic:
apply Subset.trans (vars_mul _ _)
theorem wittPolyProd_vars (n : ℕ) : (wittPolyProd p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [wittPolyProd]
  apply Subset.trans (vars_mul _ _)
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars ((rename (Prod.mk 0)) (wittPolynomial p ℤ n)) ∪ vars ((rename (Prod.mk 1)) (wittPolynomial p ℤ n)) ⊆
    univ ×ˢ range (n + 1)

Next tactic:
refine' union_subset _ _
theorem wittPolyProd_vars (n : ℕ) : (wittPolyProd p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [wittPolyProd]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · 

Proof state:
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars ((rename (Prod.mk 0)) (wittPolynomial p ℤ n)) ⊆ univ ×ˢ range (n + 1)

Next tactic:
refine' Subset.trans (vars_rename _ _) _
theorem wittPolyProd_vars (n : ℕ) : (wittPolyProd p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [wittPolyProd]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_rename _ _) _
    

Proof state:
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ image (Prod.mk 0) (vars (wittPolynomial p ℤ n)) ⊆ univ ×ˢ range (n + 1)

Next tactic:
simp [wittPolynomial_vars, image_subset_iff]
theorem wittPolyProd_vars (n : ℕ) : (wittPolyProd p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [wittPolyProd]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · 

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars ((rename (Prod.mk 1)) (wittPolynomial p ℤ n)) ⊆ univ ×ˢ range (n + 1)

Next tactic:
refine' Subset.trans (vars_rename _ _) _
theorem wittPolyProd_vars (n : ℕ) : (wittPolyProd p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [wittPolyProd]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_rename _ _) _
    

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ image (Prod.mk 1) (vars (wittPolynomial p ℤ n)) ⊆ univ ×ˢ range (n + 1)

Next tactic:
simp [wittPolynomial_vars, image_subset_iff]
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (wittPolyProdRemainder p n) ⊆ univ ×ˢ range n

Next tactic:
rw [wittPolyProdRemainder]
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (∑ i in range n, ↑p ^ i * wittMul p i ^ p ^ (n - i)) ⊆ univ ×ˢ range n

Next tactic:
refine' Subset.trans (vars_sum_subset _ _) _
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ (Finset.biUnion (range n) fun i => vars (↑p ^ i * wittMul p i ^ p ^ (n - i))) ⊆ univ ×ˢ range n

Next tactic:
rw [biUnion_subset]
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  rw [biUnion_subset]
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ∀ x ∈ range n, vars (↑p ^ x * wittMul p x ^ p ^ (n - x)) ⊆ univ ×ˢ range n

Next tactic:
intro x hx
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  rw [biUnion_subset]
  intro x hx
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ vars (↑p ^ x * wittMul p x ^ p ^ (n - x)) ⊆ univ ×ˢ range n

Next tactic:
apply Subset.trans (vars_mul _ _)
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  rw [biUnion_subset]
  intro x hx
  apply Subset.trans (vars_mul _ _)
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ vars (↑p ^ x) ∪ vars (wittMul p x ^ p ^ (n - x)) ⊆ univ ×ˢ range n

Next tactic:
refine' union_subset _ _
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  rw [biUnion_subset]
  intro x hx
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _
  · 

Proof state:
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ vars (↑p ^ x) ⊆ univ ×ˢ range n

Next tactic:
apply Subset.trans (vars_pow _ _)
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  rw [biUnion_subset]
  intro x hx
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _
  · apply Subset.trans (vars_pow _ _)
    

Proof state:
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ vars ↑p ⊆ univ ×ˢ range n

Next tactic:
have : (p : 𝕄) = C (p : ℤ) := by simp only [Int.cast_ofNat, eq_intCast]
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  rw [biUnion_subset]
  intro x hx
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _
  · apply Subset.trans (vars_pow _ _)
    have : (p : 𝕄) = C (p : ℤ) := by 

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ ↑p = C ↑p

Next tactic:
simp only [Int.cast_ofNat, eq_intCast]
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  rw [biUnion_subset]
  intro x hx
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _
  · apply Subset.trans (vars_pow _ _)
    have : (p : 𝕄) = C (p : ℤ) := by simp only [Int.cast_ofNat, eq_intCast]
    

Proof state:
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
this : ↑p = C ↑p
⊢ vars ↑p ⊆ univ ×ˢ range n

Next tactic:
rw [this, vars_C]
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  rw [biUnion_subset]
  intro x hx
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _
  · apply Subset.trans (vars_pow _ _)
    have : (p : 𝕄) = C (p : ℤ) := by simp only [Int.cast_ofNat, eq_intCast]
    rw [this, vars_C]
    

Proof state:
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
this : ↑p = C ↑p
⊢ ∅ ⊆ univ ×ˢ range n

Next tactic:
apply empty_subset
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  rw [biUnion_subset]
  intro x hx
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _
  · apply Subset.trans (vars_pow _ _)
    have : (p : 𝕄) = C (p : ℤ) := by simp only [Int.cast_ofNat, eq_intCast]
    rw [this, vars_C]
    apply empty_subset
  · 

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ vars (wittMul p x ^ p ^ (n - x)) ⊆ univ ×ˢ range n

Next tactic:
apply Subset.trans (vars_pow _ _)
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  rw [biUnion_subset]
  intro x hx
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _
  · apply Subset.trans (vars_pow _ _)
    have : (p : 𝕄) = C (p : ℤ) := by simp only [Int.cast_ofNat, eq_intCast]
    rw [this, vars_C]
    apply empty_subset
  · apply Subset.trans (vars_pow _ _)
    

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ vars (wittMul p x) ⊆ univ ×ˢ range n

Next tactic:
apply Subset.trans (wittMul_vars _ _)
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  rw [biUnion_subset]
  intro x hx
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _
  · apply Subset.trans (vars_pow _ _)
    have : (p : 𝕄) = C (p : ℤ) := by simp only [Int.cast_ofNat, eq_intCast]
    rw [this, vars_C]
    apply empty_subset
  · apply Subset.trans (vars_pow _ _)
    apply Subset.trans (wittMul_vars _ _)
    

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ univ ×ˢ range (x + 1) ⊆ univ ×ˢ range n

Next tactic:
apply product_subset_product (Subset.refl _)
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  rw [biUnion_subset]
  intro x hx
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _
  · apply Subset.trans (vars_pow _ _)
    have : (p : 𝕄) = C (p : ℤ) := by simp only [Int.cast_ofNat, eq_intCast]
    rw [this, vars_C]
    apply empty_subset
  · apply Subset.trans (vars_pow _ _)
    apply Subset.trans (wittMul_vars _ _)
    apply product_subset_product (Subset.refl _)
    

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range n
⊢ range (x + 1) ⊆ range n

Next tactic:
simp only [mem_range, range_subset] at hx ⊢
theorem wittPolyProdRemainder_vars (n : ℕ) :
    (wittPolyProdRemainder p n).vars ⊆ univ ×ˢ range n := by
  rw [wittPolyProdRemainder]
  refine' Subset.trans (vars_sum_subset _ _) _
  rw [biUnion_subset]
  intro x hx
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _
  · apply Subset.trans (vars_pow _ _)
    have : (p : 𝕄) = C (p : ℤ) := by simp only [Int.cast_ofNat, eq_intCast]
    rw [this, vars_C]
    apply empty_subset
  · apply Subset.trans (vars_pow _ _)
    apply Subset.trans (wittMul_vars _ _)
    apply product_subset_product (Subset.refl _)
    simp only [mem_range, range_subset] at hx ⊢
    

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x < n
⊢ x + 1 ≤ n

Next tactic:
exact hx
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (remainder p n) ⊆ univ ×ˢ range (n + 1)

Next tactic:
rw [remainder]
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars
      ((∑ x in range (n + 1), (rename (Prod.mk 0)) ((monomial fun₀ | x => p ^ (n + 1 - x)) (↑p ^ x))) *
        ∑ x in range (n + 1), (rename (Prod.mk 1)) ((monomial fun₀ | x => p ^ (n + 1 - x)) (↑p ^ x))) ⊆
    univ ×ˢ range (n + 1)

Next tactic:
apply Subset.trans (vars_mul _ _)
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  

Proof state:
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (∑ x in range (n + 1), (rename (Prod.mk 0)) ((monomial fun₀ | x => p ^ (n + 1 - x)) (↑p ^ x))) ∪
      vars (∑ x in range (n + 1), (rename (Prod.mk 1)) ((monomial fun₀ | x => p ^ (n + 1 - x)) (↑p ^ x))) ⊆
    univ ×ˢ range (n + 1)

Next tactic:
refine' union_subset _ _
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · 

Proof state:
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (∑ x in range (n + 1), (rename (Prod.mk 0)) ((monomial fun₀ | x => p ^ (n + 1 - x)) (↑p ^ x))) ⊆
    univ ×ˢ range (n + 1)

Next tactic:
refine' Subset.trans (vars_sum_subset _ _) _
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_sum_subset _ _) _
    

Proof state:
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ (Finset.biUnion (range (n + 1)) fun i =>
      vars ((rename (Prod.mk 0)) ((monomial fun₀ | i => p ^ (n + 1 - i)) (↑p ^ i)))) ⊆
    univ ×ˢ range (n + 1)

Next tactic:
rw [biUnion_subset]
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_sum_subset _ _) _
    rw [biUnion_subset]
    

Proof state:
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ∀ x ∈ range (n + 1),
    vars ((rename (Prod.mk 0)) ((monomial fun₀ | x => p ^ (n + 1 - x)) (↑p ^ x))) ⊆ univ ×ˢ range (n + 1)

Next tactic:
intro x hx
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_sum_subset _ _) _
    rw [biUnion_subset]
    intro x hx
    

Proof state:
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ vars ((rename (Prod.mk 0)) ((monomial fun₀ | x => p ^ (n + 1 - x)) (↑p ^ x))) ⊆ univ ×ˢ range (n + 1)

Next tactic:
rw [rename_monomial, vars_monomial, Finsupp.mapDomain_single]
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_sum_subset _ _) _
    rw [biUnion_subset]
    intro x hx
    rw [rename_monomial, vars_monomial, Finsupp.mapDomain_single]
    · 

Proof state:
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ (fun₀ | (0, x) => p ^ (n + 1 - x)).support ⊆ univ ×ˢ range (n + 1)

Next tactic:
apply Subset.trans Finsupp.support_single_subset
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_sum_subset _ _) _
    rw [biUnion_subset]
    intro x hx
    rw [rename_monomial, vars_monomial, Finsupp.mapDomain_single]
    · apply Subset.trans Finsupp.support_single_subset
      

Proof state:
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ {(0, x)} ⊆ univ ×ˢ range (n + 1)

Next tactic:
simpa using mem_range.mp hx
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_sum_subset _ _) _
    rw [biUnion_subset]
    intro x hx
    rw [rename_monomial, vars_monomial, Finsupp.mapDomain_single]
    · apply Subset.trans Finsupp.support_single_subset
      simpa using mem_range.mp hx
    · 

Proof state:
case refine'_1
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ ↑p ^ x ≠ 0

Next tactic:
apply pow_ne_zero
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_sum_subset _ _) _
    rw [biUnion_subset]
    intro x hx
    rw [rename_monomial, vars_monomial, Finsupp.mapDomain_single]
    · apply Subset.trans Finsupp.support_single_subset
      simpa using mem_range.mp hx
    · apply pow_ne_zero
      

Proof state:
case refine'_1.h
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ ↑p ≠ 0

Next tactic:
exact mod_cast hp.out.ne_zero
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · 

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ vars (∑ x in range (n + 1), (rename (Prod.mk 1)) ((monomial fun₀ | x => p ^ (n + 1 - x)) (↑p ^ x))) ⊆
    univ ×ˢ range (n + 1)

Next tactic:
refine' Subset.trans (vars_sum_subset _ _) _
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_sum_subset _ _) _
    

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ (Finset.biUnion (range (n + 1)) fun i =>
      vars ((rename (Prod.mk 1)) ((monomial fun₀ | i => p ^ (n + 1 - i)) (↑p ^ i)))) ⊆
    univ ×ˢ range (n + 1)

Next tactic:
rw [biUnion_subset]
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_sum_subset _ _) _
    rw [biUnion_subset]
    

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n : ℕ
⊢ ∀ x ∈ range (n + 1),
    vars ((rename (Prod.mk 1)) ((monomial fun₀ | x => p ^ (n + 1 - x)) (↑p ^ x))) ⊆ univ ×ˢ range (n + 1)

Next tactic:
intro x hx
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_sum_subset _ _) _
    rw [biUnion_subset]
    intro x hx
    

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ vars ((rename (Prod.mk 1)) ((monomial fun₀ | x => p ^ (n + 1 - x)) (↑p ^ x))) ⊆ univ ×ˢ range (n + 1)

Next tactic:
rw [rename_monomial, vars_monomial, Finsupp.mapDomain_single]
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_sum_subset _ _) _
    rw [biUnion_subset]
    intro x hx
    rw [rename_monomial, vars_monomial, Finsupp.mapDomain_single]
    · 

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ (fun₀ | (1, x) => p ^ (n + 1 - x)).support ⊆ univ ×ˢ range (n + 1)

Next tactic:
apply Subset.trans Finsupp.support_single_subset
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_sum_subset _ _) _
    rw [biUnion_subset]
    intro x hx
    rw [rename_monomial, vars_monomial, Finsupp.mapDomain_single]
    · apply Subset.trans Finsupp.support_single_subset
      

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ {(1, x)} ⊆ univ ×ˢ range (n + 1)

Next tactic:
simpa using mem_range.mp hx
theorem remainder_vars (n : ℕ) : (remainder p n).vars ⊆ univ ×ˢ range (n + 1) := by
  rw [remainder]
  apply Subset.trans (vars_mul _ _)
  refine' union_subset _ _ <;>
  · refine' Subset.trans (vars_sum_subset _ _) _
    rw [biUnion_subset]
    intro x hx
    rw [rename_monomial, vars_monomial, Finsupp.mapDomain_single]
    · apply Subset.trans Finsupp.support_single_subset
      simpa using mem_range.mp hx
    · 

Proof state:
case refine'_2
p : ℕ
hp : Fact (Nat.Prime p)
k : Type u_1
inst✝ : CommRing k
n x : ℕ
hx : x ∈ range (n + 1)
⊢ ↑p ^ x ≠ 0

Next tactic:
apply pow_ne_zero