Skip to content

Discrete math 1 problem set: sets, counting, proofs, induction, relations, bijections

ModuleS-M05 · solve · none · Pass 2 · 8 to 10 h
You buildanswers in solve/S-M05.toml (34 checked by SymPy) and 18 proofs in solve/S-M05/qN.md (self-graded against their rubrics)
Contractnone: a pen and paper set
Testscourse/solve/S-M05/key.toml (hidden): typed answers plus reject canaries; the problems are in course/solve/S-M05/problems.md and in section 4
Needshigh-school algebra. Reading: the Discrete Math 1 topic, sections 1 to 6
Used byno call site (a solve set). Do it before M06.1 (toposort correctness is an induction), M06.3 (PCG32 is counting and modular arithmetic), M05.1 (parameter, FLOP, and KV-byte counts), M05.2 (the GPT-2 byte bijection), L5.2 (mask algebra), and L9.2 (the online softmax invariant)
MilestoneMS-P2 (the Pass 2 gate runs ol check on every solve part of the pass)
Optional depthHammack, Book of Proof (free), ch. 1 to 10 and 12; Velleman, How to Prove It, ch. 3 and 6
  • An attention mask is a set of allowed (query, key) pairs, so combining masks is set intersection and a fully masked row is the negation of “every row has a key” (q4, q5).
  • Every size in your system is a count: parameters are sums of matrix shapes, FLOPs are 2mkn2mkn per matmul, and KV-cache bytes are 2⋅L⋅Hkv⋅dh⋅b2 \cdot L \cdot H_{kv} \cdot d_h \cdot b per token (q9 to q15).
  • A loop is correct when an invariant holds before it, survives one iteration, and implies the result at exit; the online softmax of L9.2 is proved this way (q29, q30).
  • An equivalence relation is the same thing as “has the same image under some function”, which is how Unicode normalization groups strings (q36).
  • A bijection is injective plus surjective; GPT-2’s byte map is checked by exactly those two halves (q38 to q41).
Terminal window
ol start S-M05 # writes solve/S-M05.toml and one file per proof
ol check S-M05 # SymPy checks the answers, then asks each proof rubric (y/n)
ol check S-M05 --regrade # ask the rubrics again after you change a proof

Pass 1 gave you a running tracer: a byte bigram trained in Python, served from Rust, behind a Go gateway. Pass 2 turns it into a stack you can reason about, and the next build modules are arguments as much as code. M06.1 must order every node of the autograd graph before backward runs, and the only convincing evidence that it does is an induction over the traversal. M06.3 builds PCG32, whose state wraps modulo 2642^{64} and whose output is a counted rotation of bits. M05.1 turns a ModelConfig into parameter, FLOP, and KV-byte counts that decide whether a model fits on your laptop. L5.2 builds attention masks from boolean algebra, and L9.2 streams a softmax in one pass under a loop invariant. This set gives you the vocabulary and the proof habits those modules assume: sets and logic, counting, the standard proof methods, induction, relations, and functions.

SymbolMeaningType / shape
x∈Ax \in Axx is an element of the set AA
A⊆BA \subseteq Bevery element of AA is in BB
A∪B, A∩B, A∖BA \cup B,\ A \cap B,\ A \setminus Bunion (in either), intersection (in both), difference (in AA, not in BB)sets
AcA^ccomplement U∖AU \setminus A inside a universe UUset
∣A∣\lvert A \rvertthe number of elements of a finite setinteger
¬,∧,∨,⇒,  ⟺  \lnot, \land, \lor, \Rightarrow, \iffnot, and, or, implies, if and only ifpropositions
∀,∃\forall, \exists“for every”, “there exists”quantifiers
n!n!1⋅2⋯n1 \cdot 2 \cdots n, with 0!=10! = 1integer
(nk)\binom{n}{k}n!k!(n−k)!\frac{n!}{k!(n-k)!}, the number of kk-element subsets of an nn-setinteger
a∣ba \mid baa divides bb: b=kab = ka for an integer kkrelation
f:X→Yf: X \to Ya function: each x∈Xx \in X has exactly one image f(x)∈Yf(x) \in Y
g∘fg \circ fcomposition, x↦g(f(x))x \mapsto g(f(x))function

A set is an unordered collection of distinct elements, written by listing, {1,2,3}\{1, 2, 3\}, or by a rule, {x∈Z:x>0}\{x \in \mathbb{Z} : x > 0\}. Order and repetition do not matter: {2,1,2}={1,2}\{2, 1, 2\} = \{1, 2\}. Two sets are equal when each is a subset of the other, which is how set identities are proved: take an arbitrary element of one side and show it is in the other, then the reverse (“double inclusion”). The power set P(A)\mathcal{P}(A) is the set of all subsets of AA; it has 2∣A∣2^{\lvert A \rvert} elements, because each element is independently in or out.

A boolean mask is a set in disguise. An attention mask over TT positions is a subset of {0,…,T−1}2\{0, \dots, T-1\}^2, the pairs (query ii, key jj) that may interact, stored as a 0/1 matrix. The causal mask is {(i,j):j≤i}\{(i, j) : j \le i\}, a padding mask is {(i,j):j<L}\{(i, j) : j < L\}, and applying both is their intersection, elementwise AND.

A proposition is a statement that is true or false. Connectives build new ones, defined by truth tables: P∧QP \land Q is true when both are, P∨QP \lor Q when at least one is, ¬P\lnot P flips PP, and P⇒QP \Rightarrow Q is false only when PP is true and QQ false. Two propositions are logically equivalent when they agree on every row of the truth table. The contrapositive ¬Q⇒¬P\lnot Q \Rightarrow \lnot P is equivalent to P⇒QP \Rightarrow Q; the converse Q⇒PQ \Rightarrow P is not. De Morgan’s laws move a negation inward and swap the connective: ¬(P∨Q)  ⟺  ¬P∧¬Q\lnot (P \lor Q) \iff \lnot P \land \lnot Q and ¬(P∧Q)  ⟺  ¬P∨¬Q\lnot (P \land Q) \iff \lnot P \lor \lnot Q. For sets they read (A∪B)c=Ac∩Bc(A \cup B)^c = A^c \cap B^c.

A predicate P(x)P(x) becomes a proposition once xx is fixed. Quantifiers close it over a domain: ∀x P(x)\forall x\, P(x) (“for every xx”) and ∃x P(x)\exists x\, P(x) (“there exists xx”). Negation swaps them: ¬∀x P(x)  ⟺  ∃x ¬P(x)\lnot \forall x\, P(x) \iff \exists x\, \lnot P(x), and ¬∃x P(x)  ⟺  ∀x ¬P(x)\lnot \exists x\, P(x) \iff \forall x\, \lnot P(x). With nested quantifiers, swap each one and negate the innermost predicate.

Four rules count almost everything in this course.

  • Product rule. A choice made in kk independent steps with n1,…,nkn_1, \dots, n_k options has n1n2⋯nkn_1 n_2 \cdots n_k outcomes. Strings of length kk over an alphabet of size nn: nkn^k.
  • Ordered without repetition. Arranging kk of nn distinct items in order: n(n−1)⋯(n−k+1)=n!(n−k)!n(n-1)\cdots(n-k+1) = \frac{n!}{(n-k)!}. All nn of them: n!n!.
  • Unordered without repetition. Choosing a kk-subset: (nk)\binom{n}{k}, the ordered count divided by the k!k! orders of each subset.
  • Unordered with repetition (“stars and bars”). Placing nn identical items into kk distinct boxes is arranging nn stars and k−1k - 1 bars in a row: (n+k−1k−1)\binom{n + k - 1}{k - 1}.

The sum rule adds the sizes of disjoint cases. When the cases overlap, inclusion-exclusion corrects the double count: ∣A∪B∣=∣A∣+∣B∣−∣A∩B∣\lvert A \cup B \rvert = \lvert A \rvert + \lvert B \rvert - \lvert A \cap B \rvert.

Model sizes are counts of this kind. A matrix of shape m×nm \times n holds mnmn numbers; a layer’s parameter count is the sum over its matrices and vectors. A matrix product C=ABC = AB with AA of shape m×km \times k and BB of shape k×nk \times n computes mnmn outputs, each a sum of kk products, so it takes mknmkn multiplications and as many additions: 2mkn2mkn floating-point operations (FLOPs). A forward pass over NN parameters costs about 2N2N FLOPs per token, and training about 6N6N (the backward pass costs twice the forward), so training on DD tokens costs about 6ND6ND. The KV cache stores one key vector and one value vector of length dhd_h per KV head per layer per token, at bb bytes per number: 2LHkvdhb2 L H_{kv} d_h b bytes per token.

A proof is a finite chain of statements, each a definition, an assumption, an earlier result, or a logical consequence of earlier lines, ending in the claim. The methods differ in what they assume first.

MethodTo prove P⇒QP \Rightarrow QUse it when
Directassume PP, derive QQdefinitions unfold forward (q17)
Contrapositiveassume ¬Q\lnot Q, derive ¬P\lnot P¬Q\lnot Q gives you something to compute with (q18)
Contradictionassume PP and ¬Q\lnot Q, derive a false statementthe claim says something does not exist (q19, q20)
Casessplit PP into exhaustive cases, prove eachparity, signs, ranges (q21)
Counterexampleexhibit one xx with ¬Q(x)\lnot Q(x)disproving a ∀\forall claim (q23)
Pigeonholemore than kk objects in kk boxes put two in one boxcollisions (q24)

Definitions are the raw material: an integer nn is even if n=2kn = 2k and odd if n=2k+1n = 2k + 1 for an integer kk; a number is rational if it is p/qp/q for integers p,qp, q with q≠0q \ne 0; an integer p≥2p \ge 2 is prime if its only positive divisors are 1 and pp.

Induction proves P(n)P(n) for every integer n≥n0n \ge n_0 in two steps: the base case P(n0)P(n_0), and the inductive step “if P(k)P(k) then P(k+1)P(k + 1)” for every k≥n0k \ge n_0. The assumption P(k)P(k) is the induction hypothesis, and the step must use it rather than the conclusion. Strong induction assumes P(m)P(m) for every mm with n0≤m<nn_0 \le m < n and proves P(n)P(n); it suits claims where nn breaks into smaller pieces of arbitrary size, such as factorizations.

A loop invariant is induction over iterations. To prove a loop correct, show three things: the invariant holds before the first iteration (initialization), one iteration preserves it (maintenance), and the loop stops (termination: some nonnegative integer strictly decreases). At exit, the invariant plus the exit condition imply the result. L9.2 and M06.1 both rest on arguments of this shape.

A relation RR on a set XX is a set of ordered pairs from X×XX \times X; write xRyx R y for (x,y)∈R(x, y) \in R. It is reflexive if xRxx R x for every xx, symmetric if xRy⇒yRxx R y \Rightarrow y R x, antisymmetric if xRy∧yRx⇒x=yx R y \land y R x \Rightarrow x = y, and transitive if xRy∧yRz⇒xRzx R y \land y R z \Rightarrow x R z.

An equivalence relation is reflexive, symmetric, and transitive. Its equivalence classes [x]={y:xRy}[x] = \{y : x R y\} partition XX into disjoint nonempty blocks, and every partition comes from exactly one equivalence relation, so counting equivalence relations on an nn-set is counting its partitions (the Bell number BnB_n: B1=1,B2=2,B3=5B_1 = 1, B_2 = 2, B_3 = 5). A partial order is reflexive, antisymmetric, and transitive, like ≤\le on numbers, ⊆\subseteq on sets, or “must run before” on the nodes of a computation graph (M06.1).

A function f:X→Yf: X \to Y is injective (one-to-one) if f(x)=f(x′)⇒x=x′f(x) = f(x') \Rightarrow x = x', surjective (onto) if every y∈Yy \in Y equals some f(x)f(x), and bijective if both; a bijection has an inverse f−1f^{-1}. Between finite sets of equal size, injective and surjective imply each other. The number of functions from a kk-set to an nn-set is nkn^k, the injective ones number n!(n−k)!\frac{n!}{(n-k)!}, and the bijections of an nn-set to itself number n!n!. To prove ff injective, take x≠x′x \ne x' and show f(x)≠f(x′)f(x) \ne f(x'), often by cases on where xx and x′x' lie.

ol check parses each answer as ASCII math and compares it with the key in SymPy: an [expr] must equal the key as a formula (symbolically, or at 32 random points of its domain), a [number] marked exact must be an exact value (3/4, not 0.75), a [set] matches element for element in any order, and a [matrix] entry by entry. Feedback names what differs, never the expected answer. A proof is graded by you: ol check prints each line of its rubric and you answer y or n, and every line must be a yes.

This is a sibling of q11 and q26, not one of the graded problems.

Count. SmolLM2-135M’s attention uses grouped-query attention: width d=576d = 576, 9 query heads and 3 key/value heads of size dh=64d_h = 64, no biases. How many parameters do its four projections hold?

The query projection maps width 576 to 9⋅64=5769 \cdot 64 = 576 outputs: a 576×576576 \times 576 matrix, 331,776331{,}776 parameters. The key and value projections each map 576 to 3⋅64=1923 \cdot 64 = 192 outputs: 576⋅192=110,592576 \cdot 192 = 110{,}592 each. The output projection maps the 576 concatenated head outputs back to 576: 331,776331{,}776. Total: 2⋅331,776+2⋅110,592=884,7362 \cdot 331{,}776 + 2 \cdot 110{,}592 = 884{,}736. In solve/ this would be answer = "2*576*576 + 2*576*192": any expression with the right exact value passes. Over 30 layers that is 26,542,08026{,}542{,}080, about a fifth of the model.

Proof. Claim: 1+3+5+⋯+(2n−1)=n21 + 3 + 5 + \dots + (2n - 1) = n^2 for every integer n≥1n \ge 1.

Method: induction on nn. Base case n=1n = 1: the left side is 1=121 = 1^2. Induction hypothesis: for some k≥1k \ge 1, ∑i=1k(2i−1)=k2\sum_{i=1}^{k} (2i - 1) = k^2. Inductive step: ∑i=1k+1(2i−1)=k2+(2(k+1)−1)\sum_{i=1}^{k+1} (2i - 1) = k^2 + (2(k+1) - 1) by the hypothesis, =k2+2k+1=(k+1)2= k^2 + 2k + 1 = (k+1)^2, the claim for n=k+1n = k + 1. By induction the claim holds for every n≥1n \ge 1.

Read it against the proof rubric (course/rubrics/proof.md): the claim and every symbol are stated, the method is named, the base case is explicit, the hypothesis is stated for n=kn = k and used in the step (not the conclusion), and the last line restates the claim. Your proofs for q26 to q30 should look like this.

Write each answer in solve/S-M05.toml; lettered parts are their own tables:

[q4.a]
answer = "[[1, 0, 0, 0], [1, 1, 0, 0], [1, 1, 1, 0], [1, 1, 1, 0]]"
[q9]
answer = "m*n + m"
[q6]
proof = "S-M05/q6.md"

ASCII math: x^2, 2^32, binomial(10, 3), factorial(5), exp(-1), sets {1, 2}, matrices as lists of rows. The tag after each problem is its answer type.

q1. Let U={1,2,…,10}U = \{1, 2, \dots, 10\}, A={1,2,3,4,5,6}A = \{1, 2, 3, 4, 5, 6\} and B={2,4,6,8}B = \{2, 4, 6, 8\}. (a) A∩BA \cap B. (b) A∖BA \setminus B. (c) The complement of A∪BA \cup B in UU. [set]

q2. How many subsets of {1,2,3,4,5,6}\{1, 2, 3, 4, 5, 6\} contain 11 but not 22? [number]

q3. For propositions PP and QQ: (a) is P⇒QP \Rightarrow Q logically equivalent to ¬Q⇒¬P\lnot Q \Rightarrow \lnot P? (b) Is P⇒QP \Rightarrow Q logically equivalent to Q⇒PQ \Rightarrow P? [bool]

q4. An attention mask is a 0/1 matrix MM whose row ii is a query position and column jj a key position; Mij=1M_{ij} = 1 means “query ii may attend to key jj”. With T=4T = 4 positions, the causal mask allows j≤ij \le i and the padding mask allows j<3j < 3 (position 3 is padding). (a) Give the combined mask (causal AND padding) as a 4×44 \times 4 matrix. [matrix] (b) How many (i,j)(i, j) pairs does it allow? [number]

q5. Which statement is the negation of “for every query row ii there is a key jj with Mij=1M_{ij} = 1”? [choice] (a) There is a row ii such that Mij=0M_{ij} = 0 for every key jj. (b) Mij=0M_{ij} = 0 for every row ii and every key jj. (c) There is a row ii and a key jj with Mij=0M_{ij} = 0. (d) For every row ii there is a key jj with Mij=0M_{ij} = 0.

q6. Prove De Morgan’s law (A∪B)c=Ac∩Bc(A \cup B)^c = A^c \cap B^c for subsets A,BA, B of a universe UU. [proof]

q7. (a) In how many ways can you choose 3 of 10 attention heads to prune? (b) How many byte strings of length 4 are there? (c) How many entries does a byte bigram table have (ordered pairs of bytes, repeats allowed)? [number]

q8. In how many ways can 5 identical tokens be placed into 3 distinct buckets, empty buckets allowed? [number]

q9. A linear layer y=Wx+by = Wx + b maps Rn\mathbb{R}^n to Rm\mathbb{R}^m. How many parameters does it have? [expr in m, n]

q10. A language model has an embedding table with VV rows of width dd and an untied output head that maps width dd to VV logits without a bias. How many parameters do the two hold together? [expr in V, d]

q11. A decoder block of width dd has four d×dd \times d attention projections (Q,K,V,OQ, K, V, O) without biases, an MLP d→4d→dd \to 4d \to d (two matrices, no biases), and two RMSNorm gain vectors of length dd. How many parameters does the block have? [expr in d]

q12. Counting one multiplication and one addition as two floating-point operations, how many FLOPs does the product of an m×km \times k matrix and a k×nk \times n matrix take? [expr in m, k, n]

q13. The training-compute rule of thumb is C≈6NDC \approx 6ND FLOPs for NN parameters and DD tokens. Give CC for N=107N = 10^7 and D=2×108D = 2 \times 10^8. [number]

q14. SmolLM2-135M has 30 layers, 3 key/value heads, and head dimension 64, and caches keys and values in bf16 (2 bytes per number). How many bytes of KV cache does one token take? [number]

q15. How many bytes does that cache take for a context of 2048 tokens? [number]

q16. How many integers in {1,2,…,100}\{1, 2, \dots, 100\} are divisible by 3 or by 5? [number]

q17. Prove directly: if nn is an odd integer, then n2n^2 is odd. [proof]

q18. Prove by contrapositive: if nn is an integer and n2n^2 is even, then nn is even. [proof]

q19. Prove by contradiction: 2\sqrt{2} is irrational. [proof]

q20. Prove that there are infinitely many primes. [proof]

q21. Prove by cases: n2+nn^2 + n is even for every integer nn. [proof]

q22. Prove: for real a,b≥0a, b \ge 0, a+b2≥ab\frac{a + b}{2} \ge \sqrt{ab}, with equality exactly when a=ba = b. [proof]

q23. Claim: n2−n+41n^2 - n + 41 is prime for every integer n≥1n \ge 1. (a) Is the claim true? [bool] (b) Give the smallest n≥1n \ge 1 for which n2−n+41n^2 - n + 41 is not prime. [number]

q24. Prove (pigeonhole): any function from a set of 257 byte strings to 8-bit hash values maps two different strings to the same value. [proof]

q25. Prove: the sum of a rational number and an irrational number is irrational. [proof]

q26. Prove by induction: 1+2+⋯+n=n(n+1)21 + 2 + \dots + n = \frac{n(n+1)}{2} for every integer n≥1n \ge 1. [proof]

q27. Prove by induction: 2n>n22^n > n^2 for every integer n≥5n \ge 5. [proof]

q28. Prove by strong induction: every integer n≥2n \ge 2 is a product of one or more primes. [proof]

q29. Prove that this loop returns xnx^n for every integer n≥0n \ge 0, using the invariant r⋅be=xnr \cdot b^e = x^n (the same squaring trick computes PCG32’s jump-ahead):

r = 1; b = x; e = n
while e > 0:
if e is odd: r = r * b
b = b * b
e = floor(e / 2)
return r

[proof]

q30. The online softmax (the C kernel of L9.2) reads x0,x1,…x_0, x_1, \dots once, keeping a running maximum mm and a running sum ss. It starts at m=−∞m = -\infty, s=0s = 0 (with e−∞=0e^{-\infty} = 0), and for each new xix_i sets m′=max⁡(m,xi)m' = \max(m, x_i) and s′=s⋅em−m′+exi−m′s' = s \cdot e^{m - m'} + e^{x_i - m'}. Prove that after reading x0,…,xi−1x_0, \dots, x_{i-1} it holds that m=max⁡j<ixjm = \max_{j < i} x_j and s=∑j<iexj−ms = \sum_{j < i} e^{x_j - m}. [proof]

q31. Give a closed form for 12+22+⋯+n21^2 + 2^2 + \dots + n^2. [expr in n]

q32. Give a closed form for 20+21+⋯+2n−12^0 + 2^1 + \dots + 2^{n-1}. [expr in n]

q33. Run the loop of q30 on x=(1,3,2)x = (1, 3, 2). Give the final ss exactly. [number]

q34. Let R={(1,1),(2,2),(3,3),(1,2),(2,1)}R = \{(1,1), (2,2), (3,3), (1,2), (2,1)\} on {1,2,3}\{1, 2, 3\}. Is RR (a) reflexive, (b) symmetric, (c) transitive? [bool]

q35. How many equivalence relations are there on a 4-element set? [number]

q36. Prove: for any function f:X→Yf: X \to Y, the relation x∼y  ⟺  f(x)=f(y)x \sim y \iff f(x) = f(y) is an equivalence relation on XX. (Unicode normalization in L1.1 is this relation with f=NFCf = \mathrm{NFC}.) [proof]

q37. Prove: divisibility (a∣ba \mid b when b=kab = ka for some integer kk) is a partial order on the positive integers. [proof]

q38. Let f:Z→Zf: \mathbb{Z} \to \mathbb{Z}, f(n)=2n+1f(n) = 2n + 1. Is ff (a) injective, (b) surjective? [bool]

q39. (a) How many bijections are there from a 5-element set to itself? (b) How many injective functions are there from a 3-element set to a 5-element set? [number]

q40. Prove: if f:X→Yf: X \to Y and g:Y→Zg: Y \to Z are bijections, then g∘fg \circ f is a bijection. [proof]

q41. GPT-2’s byte-to-character map (M05.2) keeps the 188 printable bytes P={33,…,126}∪{161,…,172}∪{174,…,255}P = \{33, \dots, 126\} \cup \{161, \dots, 172\} \cup \{174, \dots, 255\} as themselves (f(b)=bf(b) = b) and sends the other 68 bytes, in increasing order, to 256,257,…,323256, 257, \dots, 323. Prove that f:{0,…,255}→Nf: \{0, \dots, 255\} \to \mathbb{N} is injective, so it is a bijection onto its image. [proof]

PitfallSymptomCaught by
Combining masks with OR, or forgetting the padding keya pad position gets attention weightq4 (canary: the causal-only mask)
Negating only the inner predicate of a nested quantifieryou test “some entry is 0” instead of “some row is all 0”q5 (canary: choice c)
Counting multiply-adds instead of FLOPsFLOP and roofline numbers off by 2q12 (canary mkn)
Using 2ND2ND (forward only) for training computea training budget 3 times too smallq13 (canary 2*10^15)
Caching keys only, or sizing the cache by query headsKV memory off by 2 or by the GQA group sizeq14 (canaries 11520 and 69120)
Adding overlapping cases twiceinclusion-exclusion overcountq16 (canary 53)
Checking many cases instead of provinga “for every nn” claim believed from n=1n = 1 to 4040q23 (canary 40)
Using the conclusion inside the inductive stepa circular proof that the rubric rejectsq26 to q30 rubric line 2 or 3
Forgetting the running sum must be rescaled when the max changesonline softmax overflows or is wrong after a new maxq30 rubric, q33 (canary without the shift)
Confusing all functions with injective onesnkn^k where n!(n−k)!\frac{n!}{(n-k)!} was askedq39 (canaries 3125 and 125)
DirectionModuleHow it uses this
ForwardM06.1toposort over the autograd graph; its correctness proof is an induction over the traversal (S-M06a q20)
ForwardM06.3PCG32 and SplitMix64: counting bits, rotations, and arithmetic modulo 2642^{64}
ForwardM05.1param_count, flops_per_token, kv_bytes_per_token, memory_plan are q9 to q15 as code
ForwardM05.2bytes_to_unicode is the bijection of q41; its tests check injective and surjective
ForwardL5.2causal and padding masks combined as sets (q4, q5)
ForwardL9.2the online softmax kernel in C; q30 is its correctness argument
ForwardL1.1Unicode normalization as an equivalence relation (q36)
ForwardS-M06agraphs, modular arithmetic, and hashing build on these counting and proof tools