Short Notes: Maths & Combinatronics
Last Updated :
09 Sep, 2025
Mathematical Foundations
These are the most basic but essential mathematical tools in programming. They help in performing quick checks, optimizing loops, and building logic for number-based problems. Understanding GCD, LCM, floor/ceil, and number properties like parity or binary form is fundamental.
- A number is even if it is divisible by 2, i.e., n % 2 == 0; otherwise, it is odd.
- Floor of a number gives the greatest integer less than or equal to it.
- Ceil gives the smallest integer greater than or equal to the number.
- The sum of the first n natural numbers is: Sum = (n(n+1))/2
- The GCD (Greatest Common Divisor) of two numbers a and b is the largest number that divides both.
- Found using the Euclidean algorithm: gcd(a,b)=gcd(b,a%b)
- The LCM (Least Common Multiple) is the smallest number that is divisible by both a and b.
- Formula: lcm(a,b)= (a x b)/ gcd(a,b)
- A number is called a perfect number if it is equal to the sum of its proper divisors.
- Example: 6 → divisors: 1, 2, 3 → sum = 6
- To find factors of a number n, iterate from 1 to √n and check n % i == 0. Store both i and n/i.
- Decimal to binary conversion: divide the number by 2 repeatedly, store remainders, and reverse them.
Prime Number Algorithms and Sieve Techniques
A prime number is a natural number greater than 1 that has exactly two distinct positive divisors — 1 and itself.
Basic Primality Check: To check if a number n is prime, try dividing it by numbers from 2 to n-1. If any number divides it, then n is not prime; otherwise, it is.
Optimized Method (Square Root Check): We only need to check up to √n because if n has a factor larger than √n, the corresponding smaller factor must be less than √n.
So if no number from 2 to √n divides n, then n is prime.
C++
#include <iostream>
#include <cmath>
using namespace std;
bool isPrime(int n) {
// Check if n is 1 or 0
if (n <= 1)
return false;
// Check if n is 2 or 3
if (n == 2 || n == 3)
return true;
// Check whether n is divisible by 2 or 3
if (n % 2 == 0 || n % 3 == 0)
return false;
// Check from 5 to square root of n
// Iterate i by (i+6)
for (int i = 5; i <= sqrt(n); i = i + 6)
if (n % i == 0 || n % (i + 2) == 0)
return false;
return true;
}
int main() {
int n = 7;
if(isPrime(n)) cout << "true";
else cout<<"false";
return 0;
}
C
#include <stdio.h>
#include <stdbool.h>
#include <math.h>
bool isPrime(int n) {
// Check if n is 1 or 0
if (n <= 1)
return false;
// Check if n is 2 or 3
if (n == 2 || n == 3)
return true;
// Check whether n is divisible by 2 or 3
if (n % 2 == 0 || n % 3 == 0)
return false;
// Check from 5 to square root of n
// Iterate i by (i+6)
for (int i = 5; i <= sqrt(n); i = i + 6)
if (n % i == 0 || n % (i + 2) == 0)
return false;
return true;
}
int main() {
int n = 7;
if( isPrime(n)) printf("%s","true");
else printf("%s","false");
return 0;
}
Java
class GfG {
static boolean isPrime(int n) {
// Check if n is 1 or 0
if (n <= 1)
return false;
// Check if n is 2 or 3
if (n == 2 || n == 3)
return true;
// Check whether n is divisible by 2 or 3
if (n % 2 == 0 || n % 3 == 0)
return false;
// Check from 5 to square root of n
// Iterate i by (i+6)
for (int i = 5; i <= Math.sqrt(n); i = i + 6)
if (n % i == 0 || n % (i + 2) == 0)
return false;
return true;
}
public static void main(String[] args) {
int n = 7;
if(isPrime(n)){
System.out.println("true");
}else{
System.out.println("false");
}
}
}
Python
import math
def isPrime(n):
# Check if n is 1 or 0
if n <= 1:
return False
# Check if n is 2 or 3
if n == 2 or n == 3:
return True
# Check whether n is divisible by 2 or 3
if n % 2 == 0 or n % 3 == 0:
return False
# Check from 5 to square root of n
# Iterate i by (i+6)
i = 5
while i <= math.sqrt(n):
if n % i == 0 or n % (i + 2) == 0:
return False
i += 6
return True
if __name__ == "__main__":
n = 7
if(isPrime(n)):
print("true")
else:
print("false")
C#
using System;
class GfG {
static bool isPrime(int n) {
// Check if n is 1 or 0
if (n <= 1)
return false;
// Check if n is 2 or 3
if (n == 2 || n == 3)
return true;
// Check whether n is divisible by 2 or 3
if (n % 2 == 0 || n % 3 == 0)
return false;
// Check from 5 to square root of n
// Iterate i by (i+6)
for (int i = 5; i <= Math.Sqrt(n); i += 6)
if (n % i == 0 || n % (i + 2) == 0)
return false;
return true;
}
static void Main(string[] args) {
int n = 7;
if(isPrime(n))
Console.WriteLine("true");
else
Console.WriteLine("false");
}
}
JavaScript
function isPrime(n) {
// Check if n is 1 or 0
if (n <= 1)
return false;
// Check if n is 2 or 3
if (n === 2 || n === 3)
return true;
// Check whether n is divisible by 2 or 3
if (n % 2 === 0 || n % 3 === 0)
return false;
// Check from 5 to square root of n
// Iterate i by (i+6)
for (let i = 5; i <= Math.sqrt(n); i += 6)
if (n % i === 0 || n % (i + 2) === 0)
return false;
return true;
}
// Driver Code
let n = 7;
if(isPrime(n))
console.log("true");
else
console.log("false");
Sieve of Eratosthenes: The Sieve of Eratosthenes is an efficient algorithm to find all prime numbers up to a given number n.
Note: It is much faster than checking each number individually using the basic method.
C++
#include <iostream>
#include <vector>
using namespace std;
vector<int> sieve(int n) {
// creation of boolean array
vector<bool> prime(n + 1, true);
for (int p = 2; p * p <= n; p++) {
if (prime[p] == true) {
// marking as false
for (int i = p * p; i <= n; i += p)
prime[i] = false;
}
}
vector<int> res;
for (int p = 2; p <= n; p++){
if (prime[p]){
res.push_back(p);
}
}
return res;
}
int main(){
int n = 35;
vector<int> res = sieve(n);
for(auto ele : res){
cout << ele << ' ';
}
return 0;
}
Java
class GfG {
static int[] sieve(int n) {
// creation of boolean array
boolean[] prime = new boolean[n + 1];
for (int i = 0; i <= n; i++) {
prime[i] = true;
}
for (int p = 2; p * p <= n; p++) {
if (prime[p]) {
// marking as false
for (int i = p * p; i <= n; i += p)
prime[i] = false;
}
}
// Count number of primes
int count = 0;
for (int p = 2; p <= n; p++) {
if (prime[p])
count++;
}
// Store primes in an array
int[] res = new int[count];
int index = 0;
for (int p = 2; p <= n; p++) {
if (prime[p])
res[index++] = p;
}
return res;
}
public static void main(String[] args) {
int n = 35;
int[] res = sieve(n);
for (int ele : res) {
System.out.print(ele + " ");
}
}
}
Python
def sieve(n):
#Create a boolean list to track prime status of numbers
prime = [True] * (n + 1)
p = 2
# Sieve of Eratosthenes algorithm
while p * p <= n:
if prime[p]:
# Mark all multiples of p as non-prime
for i in range(p * p, n + 1, p):
prime[i] = False
p += 1
# Collect all prime numbers
res = []
for p in range(2, n + 1):
if prime[p]:
res.append(p)
return res
if __name__ == "__main__":
n = 35
res = sieve(n)
for ele in res:
print(ele, end=' ')
C#
using System;
using System.Collections.Generic;
class GfG {
// Function to return all prime numbers up to n
static List<int> sieve(int n) {
// Boolean array to mark primes
bool[] prime = new bool[n + 1];
for (int i = 0; i <= n; i++) {
prime[i] = true;
}
// Sieve of Eratosthenes
for (int p = 2; p * p <= n; p++)
{
if (prime[p])
{
for (int i = p * p; i <= n; i += p)
{
prime[i] = false;
}
}
}
// Store primes in list
List<int> res = new List<int>();
for (int i = 2; i <= n; i++)
{
if (prime[i])
{
res.Add(i);
}
}
return res;
}
static void Main()
{
int n = 35;
List<int> res = sieve(n);
foreach (int ele in res)
{
Console.Write(ele + " ");
}
}
}
JavaScript
function sieve(n) {
// Create a boolean array to mark primes
let prime = new Array(n + 1).fill(true);
// 0 and 1 are not prime
prime[0] = prime[1] = false;
// Apply Sieve of Eratosthenes
for (let p = 2; p * p <= n; p++) {
if (prime[p]) {
// Mark all multiples of p as not prime
for (let i = p * p; i <= n; i += p) {
prime[i] = false;
}
}
}
// Collect all primes into result array
let res = [];
for (let p = 2; p <= n; p++) {
if (prime[p]) {
res.push(p);
}
}
return res;
}
// Driver code
let n = 35;
let res = sieve(n);
console.log(res.join(' '));
Output2 3 5 7 11 13 17 19 23 29 31
Prime Factorization Techniques:
Optimised Trial Division:
- Try dividing n by all numbers up to √n, starting from 2.
- After removing all factors of 2, check only odd numbers.
- If n is still greater than 1, it's a prime factor itself.
Using Sieve + SPF (Smallest Prime Factor):
- The sieve precomputes and stores the smallest prime factor (SPF) for every number up to n.
- Then, to factorize any number, we repeatedly look up spf[n] and divide n by it, collecting the prime factors efficiently.
We can also count the number of Prime factors using this approach.
Number of Prime Factor:
If the prime factorization of a number n is: {\scriptstyle n \,=\, p_1^{e_1} \times p_2^{e_2} \times \cdots \times p_k^{e_k}} Then the total number of divisors of n is:{\scriptstyle (e_1 + 1) \times (e_2 + 1) \times \cdots \times (e_k + 1)}.
Each exponent eᵢ gives us (eᵢ + 1) choices (from pᵢ⁰ to pᵢ^eᵢ) in forming a divisor.
Multiplying all such choices gives the total number of divisors.
Modular Arithmetic
Modular arithmetic is a system of arithmetic where numbers “wrap around” after reaching a certain value, called the modulus. It is commonly used in programming, cryptography, and number theory.
We can write:
a%m = remainder when a is divided by m
Addition Modulo: Modular addition ensures results stay within bounds by applying the modulus after addition: (a+b)%m = [(a %m) +(b % m)]%m
Subtraction Modulo: Modular subtraction also keeps results within bounds by applying the modulus after subtraction: (a−b)%m = [(a%m)−(b %m)+m] %m
Note: Adding m before applying modulus in subtraction avoids negative results.
Multiplication Modulo: Useful for avoiding overflow in large calculations.
Modular multiplication keeps the result within bounds:
(a×b)%m=[(a%m)×(b%m)]%m
Division Modulo: In modular arithmetic, we cannot divide numbers directly. To divide a by b under modulo m, we use the modular inverse of b.
We use the modular inverse: (a/b)%m = (a x b-1) %m is the modular inverse of b modulo m.
To calculate the modular inverse when the number and modulus are coprime and the modulus is prime, we use Fermat’s Little Theorem.
If gcd(b,m)=1 and m is a prime number, then: b−1≡bm−2%m
Use modular exponentiation to calculate bm−2 mod m, which is fast and avoids overflow.
Binary Exponentiation: Used calculate ab mod m efficiently in O(log b) time
Instead of multiplying a b times, we break the power into squares: ab=a1×a2×a4×…
Only include the terms where the bit in b is set (1).
C++
#include<iostream>
using namespace std;
int powMod(int x, int n, int M) {
int res = 1;
// Loop until exponent becomes 0
while(n >= 1) {
// n is odd, multiply result by current x and take modulo
if(n & 1) {
res = (res * x) % M;
// Reduce exponent by 1 to make it even
n--;
}
// n is even, square the base and halve the exponent
else {
x = (x * x) % M;
n /= 2;
}
}
return res;
}
int main() {
int x = 3, n = 2, M = 4;
cout << powMod(x, n, M) << endl;
}
Java
class GfG {
public int powMod(int x, int n, int M) {
int res = 1;
// Loop until exponent becomes 0
while (n >= 1) {
// n is odd, multiply result by current x and take modulo
if ((n & 1) == 1) {
res = (res * x) % M;
// Decrease n to make it even
n--;
} else {
// n is even, square the base and halve the exponent
x = (x * x) % M;
n /= 2;
}
}
return res;
}
public static void main(String[] args) {
int x = 3, n = 2, M = 4;
GfG obj = new GfG();
System.out.println(obj.powMod(x, n, M));
}
}
Python
def powMod(x, n, M):
res = 1
# Loop until exponent becomes 0
while n >= 1:
# n is odd, multiply result by current x and take modulo
if n % 2 == 1:
res = (res * x) % M
# Make n even
n -= 1
else:
# n is even, square the base and halve the exponent
x = (x * x) % M
n //= 2
return res
if __name__ == "__main__":
x, n, M = 3, 2, 4
print(powMod(x, n, M))
C#
using System;
class GfG {
public int powMod(int x, int n, int M) {
int res = 1;
// Loop until exponent becomes 0
while (n >= 1) {
// n is odd, multiply result by current x and take modulo
if ((n & 1) == 1) {
res = (int)((1L * res * x) % M);
// Reduce exponent by 1
n--;
} else {
// n is even, square the base and halve the exponent
x = (int)((1L * x * x) % M);
n /= 2;
}
}
return res;
}
public static void Main() {
int x = 3, n = 2, M = 4;
GfG obj = new GfG();
Console.WriteLine(obj.powMod(x, n, M));
}
}
JavaScript
function powMod(x, n, M) {
let res = 1;
// Loop until exponent becomes 0
while (n >= 1) {
// If n is odd, multiply result by current x and take modulo
if (n % 2 === 1) {
res = (res * x) % M;
n -= 1;
} else {
// If n is even, square the base and halve the exponent
x = (x * x) % M;
n /= 2;
}
}
return res;
}
// Driver Code
let x = 3, n = 2, M = 4;
console.log(powMod(x, n, M));
Euler’s Totient & Inclusion-Exclusion Techniques
Euler’s Totient Function (φ(n))
The Euler Totient Function, denoted as φ(n), counts the number of positive integers ≤ n that are coprime to n.
If the prime factorization of n is: n = p1e1 x p2e2 x ⋯ x pkek
Then: ϕ(n)=n x (1−1/p1) x (1−1/p2) x⋯x (1−1/pk)
Inclusion-Exclusion Principle (IEP) helps us count the total number of elements in the union of overlapping sets by adding the sizes of individual sets and then subtracting overlaps, so we don’t count anything more than once.
Generalized Formula: ∣⋃ni=1 Ai∣ =∑∣Ai∣−∑∣Ai∩Aj∣+∑∣Ai ∩ Aj ∩ Ak∣− ⋯ + (−1)n + 1× ∣A1 ∩ A2 ∩ ⋯ ∩An∣
Explanation:
- Add all individual set sizes.
- Subtract the sizes of pairwise intersections.
- Add the sizes of triple intersections.
- Continue alternating signs until the intersection of all sets.
Example for 3 sets (A, B, C): ∣A∪B∪C∣=∣A∣+∣B∣+∣C∣−∣A∩B∣−∣B∩C∣−∣A∩C∣+∣A∩B∩C∣
Explore
DSA Fundamentals
Data Structures
Algorithms
Advanced
Interview Preparation
Practice Problem