05. Loops — Homework Solutions
The answer .cpp files are in
exercises/05/homework/solutions/.
Open this page after trying on your own. Compare your line of thinking with the How to think about it section, not the code line by line: two pieces of code with different shapes can both be correct, and what is worth copying is how to get there. The Test section of each problem contains input and output that have already been checked — run your own answer with that input before considering yourself done.
Running one of the answers:
g++ -std=c++17 -O2 -o jawab exercises/05/homework/solutions/01-jumlah-n.cpp
./jawab
Problem 1 — Sum from 1 to N
Problem. Read n up to 1,000,000, print
the sum from 1 to n.
How to think about it. An ordinary accumulation
pattern. What is being tested here is the choice of type: for
n = 1,000,000, the result is 500,000,500,000 — about 5 ×
10¹¹, far past the limit of int. The accumulator must be
long long.
Walkthrough.
int n;
cin >> n;
long long total = 0;
for (int i = 1; i <= n; i++) total += i;
cout << total << "\n";The formula n × (n + 1) / 2 gives the same answer
without a loop:
long long total = (long long)n * (n + 1) / 2;The (long long)n form matters: without it,
n * (n + 1) is computed as int and overflows
before it can be stored.
Tests.
| Input | Output |
|---|---|
1 |
1 |
3 |
6 |
1000000 |
500000500000 |
The third row is a data type check: with an int
accumulator, the program prints 1784293664 — a number that
looks nothing like the correct answer, and comes with no error message
at all.
Common mistakes.
- Using
int total. The result is a negative number with no error message. - Using the formula but forgetting the cast, so the result is still wrong.
Problem 2 — Digit sum
Problem. Sum the digits of a number up to 10¹⁸.
How to think about it. Take the last digit with
% 10, add it to the accumulator, drop that digit with
/ 10, repeat while the number is still greater than zero.
Because the limit is 10¹⁸, the number read must be
long long; the sum accumulator may be int
because its maximum is only 19 × 9 = 171.
Walkthrough.
long long n;
cin >> n;
int jumlah = 0;
while (n > 0) {
jumlah += n % 10;
n /= 10;
}
cout << jumlah << "\n";Tests.
| Input | Output |
|---|---|
5 |
5 |
4071 |
12 |
999999999999999999 |
162 |
The last row tests two things at once: an 18-digit number only fits
in long long, and its digit sum (18 × 9 = 162) confirms
that all the digits were read, not just some.
Common mistakes.
- Reading into an
intfor 10¹⁸ input.cinwill fail andnholds an unpredictable value. - Writing
while (n >= 0), which never stops because0 / 10is still0.
Problem 3 — Multiplication table
Problem. Print an n × n table, numbers
separated by spaces, with no space at the end of the row.
How to think about it. Two nested loops: the outer
one handles rows, the inner one handles columns. The tricky part is the
spaces. If you write cout << i * j << " ",
every row ends with an extra space. Some judges forgive it, some do not
— get used to the safe way: print the space before the
number, except for the first number.
Walkthrough.
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
if (j > 1) cout << " ";
cout << i * j;
}
cout << "\n";
}Tests. Input 3 produces:
1 2 3
2 4 6
3 6 9
Check that there is no space at the end of a row. The easiest way: print the space before the number except for the first column, or print the number followed by a space except for the last column.
Common mistakes.
- Putting
cout << "\n"inside the inner loop, so every number lands on its own line. - Using
endlinside a large loop. For output of thousands of lines,"\n"is much faster.
Problem 4 — Number triangle
Problem. Print a triangle pattern containing the numbers 1 up to the row number.
How to think about it. Look at the relationship
between the row number and its contents: row b contains the
numbers 1 to b. So the bound of the inner loop is the outer
loop's variable. This is the same pattern as the star triangle in the
chapter, only what is printed changes from * to the column
number.
Walkthrough.
for (int baris = 1; baris <= n; baris++) {
for (int kolom = 1; kolom <= baris; kolom++) {
cout << kolom;
}
cout << "\n";
}Tests. Input 4 produces:
1
12
123
1234
Note the relationship between a row and its contents: row
i contains the numbers 1 to i.
That means the bound of the inner loop depends on the outer loop — the
same shape as the star triangle in Chapter 05.
Common mistakes.
- Writing
kolom <= nin the inner loop, so every row has the same length. - Printing
barisinstead ofkolom, so the output is1 / 22 / 333.
Challenge — Prime number test
Problem. Determine whether n up to 10¹²
is prime or not.
How to think about it. Checking every number from 2
to n − 1 means 10¹² steps — it would take hours. The key:
if n = a × b with a ≤ b, then
a ≤ √n. This means that if there is no factor up to the
square root of n, there will be no factor at all. The
number of steps drops to 10⁶, finished in a fraction of a second.
Write the condition as i * i <= n, not
i <= sqrt(n): sqrt works with
double and can be off by one for large numbers.
Do not forget two edge cases: n = 0 and
n = 1 are not prime, while n = 2 is prime.
Walkthrough.
long long n;
cin >> n;
if (n < 2) {
cout << "BUKAN\n";
return 0;
}
bool prima = true;
for (long long i = 2; i * i <= n; i++) {
if (n % i == 0) {
prima = false;
break;
}
}
cout << (prima ? "PRIMA" : "BUKAN") << "\n";Tests.
| Input | Output |
|---|---|
1 |
BUKAN |
2 |
PRIMA |
97 |
PRIMA |
100 |
BUKAN |
999999937 |
PRIMA |
The first row is the edge case most often missed: 1 is
not a prime number, but the loop i * i <= n never runs
for n = 1, so the program answers PRIMA unless
it is given a special check. The last row tests speed: with the square
root approach it takes only about 31,623 iterations, while checking up
to n - 1 requires almost a billion iterations.
Common mistakes.
- Writing
int iin the loop. Fornclose to 10¹²,i * ioverflows as anint. - Forgetting
break. The program is still correct, but it does the rest of the loop for nothing. - Answering
PRIMAforn = 1, because the loop never runs andprimastaystrue.
OSN-style exercises — walkthrough
The answer files are in
exercises/05/osn/solutions/.
Problem 1 — Collatz Sequence
How to think about it. The number of steps is not
known before running, so the form is while, not
for. The stopping condition is taken directly from the
problem statement: "as long as the number is not yet equal to 1".
The part that decides whether the answer is right or wrong is not the
loop but the data type. The constraint N ≤ 10⁶ tempts you
to use int, but the values that appear in the
middle of the sequence are much larger than N.
Walkthrough.
long long n;
cin >> n;
long long langkah = 0;
while (n != 1) {
if (n % 2 == 0) n /= 2;
else n = 3 * n + 1;
langkah++;
}
cout << langkah << "\n";Tests.
| Input | Output | What is checked |
|---|---|---|
1 |
0 |
already 1 from the start, loop does not run |
6 |
8 |
problem sample |
27 |
111 |
a short number with a famously long sequence |
704511 |
242 |
largest intermediate value within these constraints |
The last row is a type check. Starting from 704,511, the sequence
reaches 56,991,483,520 — the largest value that appears for any
N up to 10⁶. With an int accumulator, that
value overflows, the sequence veers onto the wrong path, and the program
prints 211 instead of 242. There is no error message at all.
Common mistakes.
- Using
int. The program still runs and still prints a number. - Counting the step before the rule is applied, so
N= 1 gives 1, not 0. - Writing
while (n > 1)and then adding a branch for evennonly. For this problemwhile (n > 1)is also correct, but only because the sequence is guaranteed to come down to 1; the safer habit is to copy the stopping condition from the problem statement as is.
Problem 2 — Palindrome Number
How to think about it. Reversing a number uses the
same % 10 and / 10 pair as the Processing
digits section of Chapter 05, but in the opposite direction: each
digit taken from the back is pushed onto the front of the accumulator
with balik = balik * 10 + digit.
One trap: the loop consumes n, so the original value
must be copied before the loop starts. Otherwise, at the end there is
nothing left to compare.
The number of iterations is the number of digits — at most 19 for
these constraints — not N times.
Walkthrough.
long long n;
cin >> n;
long long asli = n;
long long balik = 0;
while (n > 0) {
balik = balik * 10 + n % 10;
n /= 10;
}
if (balik == asli) cout << "YA\n";
else cout << "TIDAK\n";Tests.
| Input | Output | What is checked |
|---|---|---|
12321 |
YA |
problem sample |
12345 |
TIDAK |
not a palindrome |
7 |
YA |
a single digit is always a palindrome |
10 |
TIDAK |
zero at the end |
1000000000000000000 |
TIDAK |
upper bound, and a type test |
The 10 row deserves attention: its reverse is 01, which
as a number has the value 1, so the answer is TIDAK. This
is correct — and it is also the reason storing the digits as text is not
needed.
Common mistakes.
- Forgetting to copy
nintoasli("original"), so at the endnis already 0. - Using
int, so a number at the upper bound cannot be read at all. - Writing
balik = balik + n % 10 * 10. The order is wrong: the old accumulator must be shifted one digit to the left first.
Problem 3 — Number of Factors
How to think about it. The most direct way is to
check every i from 1 to N and count those that
divide evenly. For N ≤ 100,000 and T ≤ 50,
that is about 5 × 10⁶ checks — still fits.
But there is a much better way, and it is worth getting used to now:
factors always come in pairs. If i divides
N evenly, then so does N / i. One of the pair
is certainly no larger than the square root of N, so it is
enough to check i up to i × i ≤ N and count
two factors at once. The exception is square numbers, where
i and N / i have the same value and must be
counted only once.
Walkthrough.
int t;
cin >> t;
for (int kasus = 0; kasus < t; kasus++) {
int n;
cin >> n;
int banyak = 0;
for (int i = 1; (long long)i * i <= n; i++) {
if (n % i == 0) {
banyak++; // factor i
if (i != n / i) banyak++; // its pair n/i
}
}
cout << banyak << "\n";
}Note that banyak is reset to zero inside the test case
loop. This is the most common mistake in multi-case problems: an
accumulator declared outside carries leftover counts from the previous
case.
Tests.
Input (after T) |
Output | What is checked |
|---|---|---|
12 |
6 |
problem sample |
1 |
1 |
smallest number |
97 |
2 |
prime number |
100000 |
36 |
upper bound |
Also test square numbers such as 36, whose answer is
9: if the i != n / i check is removed, the
number 6 is counted twice and the answer becomes 10.
Common mistakes.
- Putting
int banyak = 0;outside the test case loop. - Forgetting
i != n / i, so every square number gets one extra factor. - Starting the loop from
i = 0, which immediately causes a division by zero and a Runtime Error.
If you are still stuck
- The loop runs one time too many or too few → Chapter 05, the iterations table.
- The accumulator has a strange value → Chapter 05, the initial value table in the The accumulation pattern section.
- The program hangs → Chapter 05, the section When a loop will not stop.
Before moving on to Chapter 06, make sure you can write from memory:
the pattern for summing n numbers, the pattern for finding
the largest value, and the pattern for processing digits with
% 10 and / 10.