Modular Arithmetic Basics in DSA C++ - Time & Space Complexity
We want to understand how long modular arithmetic operations take as numbers get bigger.
How does the time to compute remainders or modular sums grow with input size?
Analyze the time complexity of the following code snippet.
int modAdd(int a, int b, int m) {
return (a % m + b % m) % m;
}
int modMul(int a, int b, int m) {
return (int)((long long)(a % m) * (b % m) % m);
}
This code calculates modular addition and modular multiplication of two numbers.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: Simple arithmetic and modulo operations.
- How many times: Each operation runs once per function call.
Each modular operation takes about the same time regardless of input size.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | 3 arithmetic + 3 modulo |
| 100 | 3 arithmetic + 3 modulo |
| 1000 | 3 arithmetic + 3 modulo |
Pattern observation: The number of operations stays the same no matter how big the numbers are.
Time Complexity: O(1)
This means modular addition and multiplication take constant time no matter the input size.
[X] Wrong: "Modular operations take longer as numbers get bigger because the numbers are bigger."
[OK] Correct: Modular arithmetic uses fixed-time CPU instructions that handle numbers efficiently regardless of size within standard integer limits.
Knowing modular arithmetic runs in constant time helps you design fast algorithms that handle large numbers safely and efficiently.
"What if we used modular exponentiation instead of simple multiplication? How would the time complexity change?"
Practice
17 % 5 in modular arithmetic?Solution
Step 1: Understand the modulo operation
The modulo operator (%) gives the remainder after division of the first number by the second.Step 2: Calculate 17 % 5
Dividing 17 by 5 gives 3 with a remainder of 2.Final Answer:
2 -> Option CQuick Check:
17 divided by 5 leaves remainder 2 [OK]
- Confusing modulo with division
- Using 5 instead of remainder
- Ignoring remainder sign
a and b in C++?Solution
Step 1: Recall C++ modulo operator syntax
In C++, the modulo operator is represented by the percent sign (%).Step 2: Identify correct syntax
Among the options, onlya % bis valid C++ syntax for modulo.Final Answer:
a % b -> Option DQuick Check:
C++ uses % for modulo [OK]
- Using 'mod' keyword
- Using '//' which is floor division in some languages
- Using function call syntax incorrectly
int a = 14; int b = 4; int c = (a + b) % 5; std::cout << c << std::endl;
Solution
Step 1: Calculate sum inside parentheses
a + b = 14 + 4 = 18.Step 2: Calculate modulo 5 of the sum
18 % 5 = 3 because 5 * 3 = 15 and remainder is 3.Final Answer:
3 -> Option AQuick Check:
(14 + 4) % 5 = 18 % 5 = 3 [OK]
- Modulo before addition
- Wrong remainder calculation
- Confusing output with sum
int x = 10; int y = 0; int z = x % y; std::cout << z << std::endl;
Solution
Step 1: Check modulo divisor value
The divisor y is 0, which is invalid for modulo operation.Step 2: Understand runtime behavior
Modulo by zero causes a runtime error (division by zero).Final Answer:
Division by zero error -> Option BQuick Check:
Modulo divisor cannot be zero [OK]
- Ignoring zero divisor
- Assuming modulo by zero returns zero
- Confusing syntax error with runtime error
(a * b) % m, which of the following is a correct way to compute it without causing integer overflow in C++ when a and b can be very large?Solution
Step 1: Understand integer overflow risk
Multiplying largeintvaluesaandbdirectly can cause undefined behavior due to overflow before% m.Step 2: Safe computation using modulo properties
Using((a % m) * (b % m)) % mensures intermediate values stay within range and prevents overflow.Step 3: Why others fail
((long long)a * b) % mmay still overflow ifbis large and not casted.(a % m) * (b % m)misses final modulo.(a * b) % moverflows.Final Answer:
((a % m) * (b % m)) % m -> Option AQuick Check:
Modulo before multiply and after prevents overflow [OK]
- Modulo before multiply without final modulo
- Missing final modulo
- Direct multiplication without modulo
Ready to prove it?
Pass the test and this pattern moves unknown
