G27
Self-checkedTier 1 15 min readalgo.dc-applications

Divide and conquer applications

The standard divide and conquer algorithms of the syllabus with their recurrences: fast exponentiation, maximum subarray, counting inversions, Karatsuba multiplication, Strassen matrix multiplication, closest pair of points and linear-time selection by the median of medians; each with the idea, the recurrence, the solution and the points where GATE asks.

Why it exists

The last page defined the method; this page applies it to the problems that appear in courses and exams, and for each one answers the same three questions: how is the problem cut, how are the answers combined, and what recurrence results. Several of these algorithms are famous because they beat an obvious method by changing the exponent (multiplying two nn-digit numbers in n1.585n^{1.585} instead of n2n^2 steps, two n×nn \times n matrices in n2.807n^{2.807} instead of n3n^3), and GATE tests exactly those exponents.

Prerequisites

You need the paradigm and the Master theorem (divide and conquer).

Precise definitions

All problems below are solved with recurrences of the form T(n)=a T(n/b)+f(n)T(n) = a\,T(n/b) + f(n) (divide and conquer), apart from selection. The new definitions:

Maximum subarray. Given numbers a0,…,an−1a_0, \ldots, a_{n-1} (some negative), find max⁡i≤j(ai+⋯+aj)\max_{i \le j} (a_i + \cdots + a_j) over non-empty contiguous ranges.

Inversion. A pair i<ji < j with ai>aja_i > a_j (see elementary sorts).

Closest pair. Given nn points in the plane, find two distinct points at the smallest Euclidean distance.

Selection (order statistic). Find the kk-th smallest of nn keys; the median is k=⌈n/2⌉k = \lceil n/2 \rceil.

How it works

The table collects the recurrences of the algorithms of this and the previous pages. Each Master-form row was decided by the decision procedure of the recurrence page and confirmed by evaluating the recurrence.

Divide and conquer algorithms and their recurrences: start

Computed by a script, not typed
recurrencesolutionhow it is solved
Binary search
Maximum and minimum
Merge sort
Quicksort, balanced split
Maximum subarray (divide and conquer)
Counting inversions (merge sort based)
Closest pair of points
Karatsuba multiplication
Strassen matrix multiplication
Fast exponentiation x^n
Quicksort, worst split
Linear-time selection (median of medians)

Step 0

The standard divide and conquer algorithms, the recurrence of each and its solution. The Master form rows were decided by the decision procedure of scripts/algo_lib.py; the two other rows were confirmed by evaluating the recurrence.

0 / 12
computed by script: the quantities are measured by running C, or evaluated, one row at a time. python3 scripts/gen-algo-sort-traces.py

Fast exponentiation

To compute xnx^n: if n=1n = 1 the answer is xx; otherwise compute h=x⌊n/2⌋h = x^{\lfloor n/2 \rfloor}, square it, and multiply by xx once more if nn is odd. Since xn=(xn/2)2x^n = (x^{n/2})^2 for even nn and x⋅(x(n−1)/2)2x \cdot (x^{(n-1)/2})^2 for odd nn, this is correct. One subproblem of half the size and a constant amount of work: T(n)=T(n/2)+Θ(1)T(n) = T(n/2) + \Theta(1), so Θ(log⁡n)\Theta(\log n) multiplications instead of the n−1n - 1 of a loop. Exactly ⌊log⁡2n⌋\lfloor \log_2 n \rfloor squarings and (number of 1 bits of n)−1(\text{number of 1 bits of } n) - 1 extra multiplications are made, at most 2⌊log⁡2n⌋2 \lfloor \log_2 n \rfloor in total. The program counts them (modulo a prime-sized number to keep the values small) and checks the result against the loop.

#include <stdio.h>
 
#define MOD 1000003ULL
 
static long mults;
 
/* x^n mod MOD by repeated squaring, n >= 1: T(n) = T(n/2) + (1 or 2) multiplications */
static unsigned long long power(unsigned long long x, unsigned n) {
    if (n == 1) return x % MOD;
    unsigned long long h = power(x, n / 2);
    unsigned long long r = h * h % MOD;     /* the squaring */
    mults++;
    if (n % 2 == 1) {                       /* an odd exponent needs one more multiplication */
        r = r * x % MOD;
        mults++;
    }
    return r;
}
 
int main(void) {
    unsigned ns[] = {2, 7, 8, 100, 1000, 1023, 1024, 1000000};
    printf("%8s %6s %8s %s\n", "n", "mults", "n - 1", "same result as the loop");
    for (int t = 0; t < 8; t++) {
        unsigned n = ns[t];
        mults = 0;
        unsigned long long fast = power(3, n);
        unsigned long long slow = 3;
        for (unsigned i = 1; i < n; i++) slow = slow * 3 % MOD;
        printf("%8u %6ld %8u %s\n", n, mults, n - 1, fast == slow ? "yes" : "NO");
    }
    return 0;
}
       n  mults    n - 1 same result as the loop
       2      1        1 yes
       7      4        6 yes
       8      3        7 yes
     100      8       99 yes
    1000     14      999 yes
    1023     18     1022 yes
    1024     10     1023 yes
 1000000     25   999999 yes

For n=1000=11111010002n = 1000 = 1111101000_2: 99 squarings and 55 extra multiplications (six 1 bits minus one) give the 1414 of the table. The worst case for a given length is n=2k−1n = 2^k - 1 (all bits one): n=1023n = 1023 needs 18=2⋅918 = 2 \cdot 9.

Maximum subarray

Cut the array in the middle. The best range is entirely in the left half, entirely in the right half, or crosses the middle. The first two are the recursive calls. The best crossing range is the best suffix of the left half plus the best prefix of the right half, found by two scans of total length nn. So T(n)=2T(n/2)+Θ(n)=Θ(nlog⁡n)T(n) = 2T(n/2) + \Theta(n) = \Theta(n \log n). (A single left-to-right scan that keeps the best sum ending at the current position, Kadane's algorithm, solves it in Θ(n)\Theta(n) and is a dynamic programming idea.)

Counting inversions

Run merge sort and count while merging (merge sort). When the merge takes a key from the right half, it is smaller than all keys still waiting in the left half, so it forms one inversion with each of them: add the number of keys left in the left half. Inversions inside a half are counted by the recursive calls, so the total is left + right + crossing. The merge is linear: T(n)=2T(n/2)+Θ(n)=Θ(nlog⁡n)T(n) = 2T(n/2) + \Theta(n) = \Theta(n \log n), against Θ(n2)\Theta(n^2) for checking all pairs. For 5,1,4,2,8,7,35, 1, 4, 2, 8, 7, 3 split as 5,1,45, 1, 4 and 2,8,7,32, 8, 7, 3: the left half has 22 inversions, the right 33, and 44 pairs cross (55 and 44 each exceed 22 and 33), in total 99, the number found earlier by counting directly.

Karatsuba multiplication

Write two nn-digit numbers as x=x1B+x0x = x_1 B + x_0 and y=y1B+y0y = y_1 B + y_0, with B=2n/2B = 2^{n/2} (or 10n/210^{n/2}). Then xy=x1y1B2+(x1y0+x0y1)B+x0y0.xy = x_1 y_1 B^2 + (x_1 y_0 + x_0 y_1) B + x_0 y_0 . The schoolbook method makes four half-size products, T(n)=4T(n/2)+Θ(n)=Θ(n2)T(n) = 4T(n/2) + \Theta(n) = \Theta(n^2). Karatsuba's idea: with z2=x1y1z_2 = x_1 y_1, z0=x0y0z_0 = x_0 y_0 the middle term is x1y0+x0y1=(x1+x0)(y1+y0)−z2−z0,x_1 y_0 + x_0 y_1 = (x_1 + x_0)(y_1 + y_0) - z_2 - z_0, a third half-size product, so only three products are needed, plus additions and shifts that cost Θ(n)\Theta(n): T(n)=3T(n/2)+Θ(n)=Θ(nlog⁡23)=Θ(n1.585).T(n) = 3T(n/2) + \Theta(n) = \Theta(n^{\log_2 3}) = \Theta(n^{1.585}).

Strassen's matrix multiplication

Split each n×nn \times n matrix into four n/2×n/2n/2 \times n/2 blocks. The block formulas for C=ABC = AB need eight block products, T(n)=8T(n/2)+Θ(n2)=Θ(n3)T(n) = 8T(n/2) + \Theta(n^2) = \Theta(n^3). Strassen found seven:

M1=(A11+A22)(B11+B22),M2=(A21+A22) B11,M3=A11(B12−B22),M4=A22(B21−B11),M5=(A11+A12) B22,M6=(A21−A11)(B11+B12),M7=(A12−A22)(B21+B22),\begin{aligned} M_1 &= (A_{11} + A_{22})(B_{11} + B_{22}), & M_2 &= (A_{21} + A_{22})\,B_{11}, & M_3 &= A_{11}(B_{12} - B_{22}), & M_4 &= A_{22}(B_{21} - B_{11}),\\ M_5 &= (A_{11} + A_{12})\,B_{22}, & M_6 &= (A_{21} - A_{11})(B_{11} + B_{12}), & M_7 &= (A_{12} - A_{22})(B_{21} + B_{22}), \end{aligned}

C11=M1+M4−M5+M7,C12=M3+M5,C21=M2+M4,C22=M1−M2+M3+M6.C_{11} = M_1 + M_4 - M_5 + M_7,\quad C_{12} = M_3 + M_5,\quad C_{21} = M_2 + M_4,\quad C_{22} = M_1 - M_2 + M_3 + M_6 . It uses 1818 additions or subtractions of half-size matrices (each Θ(n2)\Theta(n^2)), so T(n)=7T(n/2)+Θ(n2)=Θ(nlog⁡27)=Θ(n2.807).T(n) = 7T(n/2) + \Theta(n^2) = \Theta(n^{\log_2 7}) = \Theta(n^{2.807}). The identities were checked symbolically, and a C program (not printed here; it is in scripts/gen-algo-sort-traces.py) multiplied random integer matrices both ways: the products agree, the number of scalar multiplications is 8k8^k for the classical method and 7k7^k for Strassen's, n=2kn = 2^k.

Scalar multiplications: classical versus Strassen: start

Computed by a script, not typed
nclassicalStrassen (measured)8^k7^kStrassen / classical
2
4
8
16
32

Step 0

Two n-by-n integer matrices (n = 2^k) are multiplied the classical way and by Strassen's recursion down to 1-by-1 blocks. Scalar multiplications are counted, and the two products are compared.

0 / 5
computed by script: the quantities are measured by running C, or evaluated, one row at a time. python3 scripts/gen-algo-sort-traces.py

Because the saving is a constant factor (7/8)k(7/8)^k with a larger constant in the additions, Strassen's method pays off only for large matrices. The formulas never swap the two factors of a product, so they are valid for blocks, which do not commute.

Closest pair of points

Sort the points by xx once (and by yy once). Cut by a vertical line into two halves of n/2n/2 points; solve each; let δ\delta be the smaller of the two closest distances. A closer pair must have one point on each side, and both points are within δ\delta of the line, so only the strip of points within δ\delta of the line matters. Sort the strip points by yy and compare each with the next few points in yy order: a point has at most 77 later points with a yy-difference below δ\delta. Such points lie in a rectangle of width 2δ2\delta and height δ\delta above it, made of two δ×δ\delta \times \delta squares (one on each side of the line); the points on one side are at least δ\delta apart, so each square holds at most 44 of them, at most 88 points including the point itself. So the combine step is linear, if the points are kept in yy order by merging (as merge sort does): T(n)=2T(n/2)+Θ(n)=Θ(nlog⁡n).T(n) = 2T(n/2) + \Theta(n) = \Theta(n \log n). If instead the strip is sorted from scratch at every level, the combine step is Θ(nlog⁡n)\Theta(n \log n) and the total becomes Θ(nlog⁡2n)\Theta(n \log^2 n). A concrete case: the points (1,1),(4,5),(6,2),(7,8)(1,1), (4,5), (6,2), (7,8) on the left and (8,3),(11,9),(13,4),(15,7)(8,3), (11,9), (13,4), (15,7) on the right. Both halves have closest distance 13≈3.61\sqrt{13} \approx 3.61 (pairs (4,5)(4,5)–(6,2)(6,2) and (13,4)(13,4)–(15,7)(15,7)). The strip around x=7.5x = 7.5 holds the points with xx from 44 to 1111; sorted by yy they are (6,2),(8,3),(4,5),(7,8),(11,9)(6,2), (8,3), (4,5), (7,8), (11,9); the very first neighbours already give (6,2)(6,2)–(8,3)(8,3) at distance 5≈2.24\sqrt 5 \approx 2.24, the overall answer (checked against all 2828 pairs).

Selection in linear time

Quickselect partitions around a pivot and recurses on the side that contains the kk-th key: expected Θ(n)\Theta(n) time, worst case Θ(n2)\Theta(n^2) (quicksort). The median of medians makes the pivot good: split the keys into groups of 55, find each group's median (constant time per group), find the median pp of these ⌈n/5⌉\lceil n/5 \rceil medians recursively, and use pp as the pivot. At least about 3n/10−63n/10 - 6 keys are smaller than pp and as many are larger (half of the group medians are at least pp, and each of those groups has three keys at least pp), so the recursive call on one side has at most 7n/10+67n/10 + 6 keys: T(n)≤T(⌈n/5⌉)+T(7n/10+6)+Θ(n).T(n) \le T(\lceil n/5 \rceil) + T(7n/10 + 6) + \Theta(n). Since 1/5+7/10=9/10<11/5 + 7/10 = 9/10 < 1 the solution is Θ(n)\Theta(n) (each level's total size shrinks by a constant factor, so the work is a geometric series dominated by the top). With groups of 33 the fractions would be 1/3+2/3=11/3 + 2/3 = 1, the recurrence T(n/3)+T(2n/3)+Θ(n)T(n/3) + T(2n/3) + \Theta(n) solves to Θ(nlog⁡n)\Theta(n \log n), and no linear bound follows; groups of 77 also work. The constants are large, so quickselect is used in practice.

Worked examples

EX 1Count the multiplications of x to the power n

Easy

x16x^{16}: four squarings (x2,x4,x8,x16x^2, x^4, x^8, x^{16}). x15x^{15}: ⌊log⁡215⌋=3\lfloor \log_2 15 \rfloor = 3 squarings and 4−1=34 - 1 = 3 extra multiplications: 66 in all (15=1111215 = 1111_2). A loop needs 1414. For an exponent with bb bits the method uses between b−1b - 1 and 2(b−1)2(b - 1) multiplications. The recurrence is T(n)=T(n/2)+1T(n) = T(n/2) + 1 (or +2+2), Θ(log⁡n)\Theta(\log n).

EX 2Count the multiplications of Strassen

Easy

For 2×22 \times 2 matrices: 77 multiplications (instead of 88). For n=2kn = 2^k: 7k7^k. For n=1024n = 1024 (k=10k = 10): 710=282 475 2497^{10} = 282\,475\,249 against 810=1 073 741 8248^{10} = 1\,073\,741\,824, about 26%26\% of the classical count. The exponent: log⁡27=2.807\log_2 7 = 2.807.

EX 3Maximum subarray by divide and conquer

Medium

Array 4,−6,3,5,−2,7,−10,64, -6, 3, 5, -2, 7, -10, 6. Left half 4,−6,3,54, -6, 3, 5: its best range is 3+5=83 + 5 = 8. Right half −2,7,−10,6-2, 7, -10, 6: best is 77. Crossing the middle: the best suffix of the left half ends at 55 and is 3+5=83 + 5 = 8 (sums of suffixes: 5,8,2,65, 8, 2, 6); the best prefix of the right half is −2+7=5-2 + 7 = 5 (prefix sums: −2,5,−5,1-2, 5, -5, 1). Crossing total: 8+5=138 + 5 = 13, the maximum of 8,7,138, 7, 13: the answer is 1313, the range 3,5,−2,73, 5, -2, 7.

EX 4Karatsuba on a small example

Medium

x=1234x = 1234, y=5678y = 5678, B=100B = 100: x1=12x_1 = 12, x0=34x_0 = 34, y1=56y_1 = 56, y0=78y_0 = 78. z2=12⋅56=672z_2 = 12 \cdot 56 = 672, z0=34⋅78=2652z_0 = 34 \cdot 78 = 2652, (x1+x0)(y1+y0)=46⋅134=6164(x_1 + x_0)(y_1 + y_0) = 46 \cdot 134 = 6164, so the middle term is 6164−672−2652=28406164 - 672 - 2652 = 2840. Then xy=672⋅104+2840⋅102+2652=6 720 000+284 000+2652=7 006 652xy = 672 \cdot 10^4 + 2840 \cdot 10^2 + 2652 = 6\,720\,000 + 284\,000 + 2652 = 7\,006\,652. Three multiplications of two-digit numbers instead of four.

EX 5Read the exponent from the idea

GATE level

(a) Multiplying two nn-bit numbers with three recursive half-size multiplications and linear extra work: T(n)=3T(n/2)+n=Θ(nlog⁡23)T(n) = 3T(n/2) + n = \Theta(n^{\log_2 3}). (b) An algorithm multiplies n×nn \times n matrices by 7 recursive calls on half-size matrices and Θ(n2)\Theta(n^2) additional work: Θ(nlog⁡27)\Theta(n^{\log_2 7}). (c) The same with 8 calls: Θ(n3)\Theta(n^3) (the leaves dominate). (d) Closest pair where the strip is sorted afresh at every level: T(n)=2T(n/2)+nlog⁡n=Θ(nlog⁡2n)T(n) = 2T(n/2) + n \log n = \Theta(n \log^2 n) (the logarithmic extension of case 2). (e) Counting inversions by checking all pairs: Θ(n2)\Theta(n^2); by the merge sort method: Θ(nlog⁡n)\Theta(n \log n).

Cheat box

Cheat box

  • Fast exponentiation: T(n)=T(n/2)+1T(n) = T(n/2) + 1, Θ(log⁡n)\Theta(\log n); ⌊log⁡2n⌋\lfloor \log_2 n \rfloor squarings ++ (ones of nn) −1- 1 multiplications.
  • Maximum subarray: best of left, right, crossing; T(n)=2T(n/2)+nT(n) = 2T(n/2) + n, Θ(nlog⁡n)\Theta(n \log n) (Kadane: Θ(n)\Theta(n)).
  • Inversions: merge sort, add the keys left in the left half when taking from the right; Θ(nlog⁡n)\Theta(n \log n).
  • Karatsuba: 33 products, T(n)=3T(n/2)+nT(n) = 3T(n/2) + n, Θ(nlog⁡23)=Θ(n1.585)\Theta(n^{\log_2 3}) = \Theta(n^{1.585}).
  • Strassen: 77 products and 1818 additions, T(n)=7T(n/2)+n2T(n) = 7T(n/2) + n^2, Θ(nlog⁡27)=Θ(n2.807)\Theta(n^{\log_2 7}) = \Theta(n^{2.807}); classical Θ(n3)\Theta(n^3).
  • Closest pair: strip of width 2δ2\delta sorted by yy, at most 77 neighbours each; Θ(nlog⁡n)\Theta(n \log n) if yy order is kept, Θ(nlog⁡2n)\Theta(n \log^2 n) if the strip is re-sorted.
  • Selection: quickselect expected Θ(n)\Theta(n), worst Θ(n2)\Theta(n^2); median of medians (groups of 55) worst case Θ(n)\Theta(n): T(n)≤T(n/5)+T(7n/10+6)+nT(n) \le T(n/5) + T(7n/10 + 6) + n.

Traps and GATE patterns

Connections

These algorithms are instances of divide and conquer whose recurrences are solved in solving recurrences. Counting inversions is merge sort with a counter (merge sort); the partition used by quickselect is that of quicksort. Kadane's linear scan for the maximum subarray is a dynamic programming idea, like the problems in dynamic programming on sequences.

PYQs

3 previous year questions from your book. I re-solved each one myself (2 by running or simulating, 1 by reasoning only); the book's key is shown next to my answer. All PYQs

GATE 2021 · Set 1 · MCQQ2 · page 108 of the book
Let P be an array containing n integers. Let t be the
lowest upper bound on the number of comparisons
of the array elements, required to find the minimum
and maximum values in an arbitrary array of n
elements. Which one of the following choices is
correct?
  • (a)t > 2n – 2
  • (b)t > ⌈ log (n) ⌉ and t <= n
  • (c)t > n and t <= 3 ⌈ n/2 ⌉
  • (d)t > 3 ⌈ n/2 ⌉⁡and t <= 2n – 2
GATE 2019 · NAT · 1 markQ5 · page 108 of the book
Consider a sequence of 14
elements:A=[-5,-10,6,3,-1,-2,13,4,-9,-1,4,12,-3
,0].The sequence sum S(i, j) = ∑j k=i
A[k].Determine the maximum of S(i ,j), where 0≤
i≤ j< 14.(Divide and conquer approach may be
used.)
GATE 2014 · Set 1 · NAT · 2 marksQ13 · page 109 of the book
The minimum number of comparisons required
finding the minimum and the maximum of 100
numbers is
ALGORITHMS

Check Out Our Gate Courses & Secure Your Dream Rank !

HINTS & SOLUTIONS

Self-check

Question 1

What is the order of the time to multiply two nn-digit numbers by Karatsuba's method, and why?

Show answer

Θ(nlog⁡23)≈Θ(n1.585)\Theta(n^{\log_2 3}) \approx \Theta(n^{1.585}): three half-size products plus linear work give T(n)=3T(n/2)+nT(n) = 3T(n/2) + n, and nlog⁡23n^{\log_2 3} dominates nn.

Question 2

How many scalar multiplications does Strassen's method use for two 8×88 \times 8 matrices if it recurses down to 1×11 \times 1?

Show answer

73=3437^3 = 343 (the classical method uses 83=5128^3 = 512).

Question 3

How many inversions cross the middle in 3,4,1,23, 4, 1, 2 (halves 3,43, 4 and 1,21, 2)?

Show answer

All four pairs (33 and 44 each exceed 11 and 22): 44 crossing inversions, and none inside the halves.

Question 4

Why does the median-of-medians recurrence give a linear bound?

Show answer

The two recursive calls are on at most n/5n/5 and 7n/10+67n/10 + 6 keys, and 1/5+7/10<11/5 + 7/10 < 1: the sizes shrink geometrically level by level, so the total work is a geometric series dominated by Θ(n)\Theta(n) at the top.

Revision card

One-screen revision

  • Fast power Θ(log⁡n)\Theta(\log n); max subarray, inversions, closest pair: Θ(nlog⁡n)\Theta(n \log n).
  • Karatsuba 3T(n/2)+n=Θ(n1.585)3T(n/2) + n = \Theta(n^{1.585}); Strassen 7T(n/2)+n2=Θ(n2.807)7T(n/2) + n^2 = \Theta(n^{2.807}).
  • Closest pair: strip of width 2δ2\delta, sorted by yy, at most 77 neighbours.
  • Selection: quickselect expected linear, worst quadratic; median of medians (groups of 55) linear worst case.
  • Do not forget the crossing case.

References

  • ·Cormen, Leiserson, Rivest, Stein, Introduction to Algorithms (3rd edition), Chapter 4 (4.1 maximum subarray, 4.2 Strassen), Chapter 9 (medians and order statistics), Chapter 33 (33.4 closest pair), Problem 2-4 (inversions)
  • ·Dasgupta, Papadimitriou, Vazirani, Algorithms, Chapter 2 (multiplication, matrix multiplication, medians)
  • ·Kleinberg and Tardos, Algorithm Design, Chapter 5 (counting inversions, closest pair, integer multiplication)

Verification

Each algorithm was re-implemented in Python independently of the descriptions on this page and compared with a brute-force or standard answer: maximum subarray against brute force and Kadane (2000 random arrays), inversions against the quadratic count (2000 arrays), closest pair against brute force (600 random point sets, including many duplicates; the number of following strip points that need a distance test never exceeded 7), median of medians against sorting (1500 arrays), Karatsuba against Python integer multiplication with exactly 3^depth base products, and fast exponentiation against floor(log2 n) + popcount(n) - 1 multiplications for every n up to 3000. Strassen: the seven products and four output formulas were verified symbolically (sympy) and by a full recursion on random matrices, which also gave 7^k products and 6(7^k - 4^k) additions; the C measurements of the tables agree. The recurrence table was decided by the Master theorem procedure and numerics. Textbook chapter references are from memory. SECOND PASS (2026-11-02, done by the assistant, not a human check): every Self-check question was solved before the printed answer was read and all agreed; the definitions, worked examples, cheat box and traps were read claim by claim and the numbers re-derived by hand or by a small script (loop counts, recurrences, merge and quicksort counts and averages, hash probes and load-factor formulas, DP tables, MST and shortest-path runs, Floyd matrices); long C programs were not re-read line by line (they are compiled and compared by npm run verify:c, and their printed outputs were checked against the prose); tables and animations are machine output and were read, not re-run; No other defect found. Status raised to self-checked; verified needs a textbook or human check.

last verified: never

My notes (saved in this browser)