Number Theory Lecture 1

GCD, Euclidean Algorithm, and Prime Numbers

Overview

Number theory is the mathematical study of integers and their properties. This lecture introduces foundational concepts that form the basis for more advanced number theory and competitive programming techniques. You'll explore what the GCD is, how to compute it using the Euclidean Algorithm, the nature of prime numbers, and efficient methods to determine primality, including the Sieve of Eratosthenes.

Part 1: Greatest Common Divisor (GCD)

The Greatest Common Divisor (GCD) of two or more integers is the largest integer that divides all of them without leaving any remainder. If two numbers have GCD = 1, they are called co-prime.

Example

gcd(24, 16):

Key Properties of GCD

Mathematical Proof

Assume a = d·x and b = d·y, then:

a - b = d·(x - y), so d divides a - b as well.

Part 2: Euclidean Algorithm

The Euclidean Algorithm is an efficient method for computing the GCD of two numbers based on the principle:

gcd(a, b) = gcd(b, a % b)

This recursive reduction continues until one value becomes zero.

Time Complexity

Each step reduces the size of the inputs significantly. The algorithm runs in O(log min(a, b)).

Code Example

int gcd(int a, int b) {
  if (b == 0) return a;
  return gcd(b, a % b);
}

Real-World Application Problem

Given two arrays A[1..n] and B[1..m], for each B[j] compute:

gcd(A[1] + B[j], A[2] + B[j], ..., A[n] + B[j])

Optimized Solution:

ll computeGCD(const vector& a) {
  ll d = 0;
  for (int i = 1; i < a.size(); ++i)
    d = gcd(d, abs(a[i] - a[0]));
  return d;
}

vector solve(const vector& a, const vector& b) {
  ll baseGCD = computeGCD(a);
  vector result;
  for (ll bj : b)
    result.push_back(gcd(a[0] + bj, baseGCD));
  return result;
}

Part 3: Prime Numbers

A prime number is a number greater than 1 that is divisible only by 1 and itself.

Examples:

Naive Primality Test

bool isPrime(int n) {
  if (n < 2) return false;
  for (int i = 2; i < n; ++i)
    if (n % i == 0) return false;
  return true;
}

Time: O(n)

Optimized Primality Test

bool isPrime(int n) {
  if (n < 2) return false;
  for (int i = 2; i * i <= n; ++i)
    if (n % i == 0) return false;
  return true;
}

Time: O(√n)

Part 4: Sieve of Eratosthenes

The Sieve of Eratosthenes is a powerful method to find all primes from 1 to n.

vector sieve(int n) {
  vector isPrime(n+1, true);
  isPrime[0] = isPrime[1] = false;
  for (int i = 2; i * i <= n; ++i) {
    if (isPrime[i]) {
      for (int j = i * i; j <= n; j += i)
        isPrime[j] = false;
    }
  }
  return isPrime;
}

Why Start from i * i?

Any composite number less than i * i would have already been marked by smaller prime factors.

Time Complexity: O(n log log n)

Summary Table

ConceptDescription
GCDLargest number dividing all input integers
Euclidean AlgorithmEfficient way using gcd(b, a % b)
Time of GCDO(log min(a, b))
Prime NumberOnly divisible by 1 and itself
Primality TestCheck if number is prime (O(sqrt(n)))
Sieve of EratosthenesEfficient method to generate primes