Medium · 2D loops

Matrix Multiplication

Every output cell is a dot product: row i of A walks arm-in-arm with column j of B, and the middle dimension m is the only thing they share. Get the three roles straight — A is n×m, B is m×k, C is n×k — and the code writes itself.

At a glance<code>C[i][j] = sum over t of A[i][t] * B[t][j]</code> — three loops, C zeroed cell by cell, dimensions n×m, m×k → n×k.

Problem

Input: The first line has n, m, k (1 ≤ each ≤ 10). Then n lines of m integers: matrix A. Then m lines of k integers: matrix B. Values from −100 to 100.

Output: n lines of k integers: the product A×B, values separated by single spaces.

Samples:

InputOutput
2 2 2
1 2
3 4
5 6
7 8
19 22
43 50
1 1 1
3
4
12

Check the first cell by hand: C[1][1] = 1·5 + 2·7 = 19. Row meets column, multiply pairwise, add — if you can do one cell, the loops just do all of them.

Your solution

main.cpp — your solution
Custom input for "Run my input"

Judging runs in your browser against hidden tests. A runaway loop is cut off after 3 seconds — still, make sure every loop has an exit. Your code is saved in this browser as you type.

Stuck? Hints

Hint 1 — Zero each cell yourself

C is a global array, and on this site's engine global arrays are not automatically zeroed (real C++ zeroes them; our interpreter does not). The safe habit anyway: C[i][j] = 0; as the first line inside the i/j loops, then accumulate with +=. Explicit beats implicit whenever memory is involved.

Hint 2 — The middle index is the hinge

The summation index t runs over m — A's columns and B's rows. A common swap of roles writes A[t][i] or B[j][t]; both compile fine and both are wrong. Say the shape out loud once: A is n by m, B is m by k — the shared m is why the multiplication is even defined.

Hint 3 — Print with the same discipline as the judge

Rows are space-separated, rows end with a newline, no trailing space after the last number of a row: print the separator before every value except the first, exactly as you did in Bubble Sort. Output formatting is part of the problem statement, not a detail.

Solution (try it first!)
#include <iostream>
using namespace std;

int A[12][12], B[12][12], C[12][12];

int main() {
    int n, m, k;
    cin >> n >> m >> k;

    for (int i = 0; i < n; i++)
        for (int j = 0; j < m; j++)
            cin >> A[i][j];
    for (int i = 0; i < m; i++)
        for (int j = 0; j < k; j++)
            cin >> B[i][j];

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < k; j++) {
            C[i][j] = 0;
            for (int t = 0; t < m; t++) {
                C[i][j] += A[i][t] * B[t][j];
            }
        }
    }

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < k; j++) {
            cout << C[i][j];
            if (j < k - 1) cout << " ";
        }
        cout << endl;
    }
    return 0;
}

The triple loop you just wrote is, verbatim, what BLAS libraries optimize into gigaflops — the mathematics never changes, only the memory layout does. You have now handled the full 2D trio: summing (Sum a Matrix), reindexing (Matrix Transpose), and combining (this one). What is left in grid land is asking questions about rectangles — 2D Range Sums.

Deep dive

Why this works

Each output cell is a dot product: row i of A against column j of B, summed over the shared dimension m. The triple loop is the definition read aloud — n×k cells, each summing m products. There is nothing to prove; the difficulty is purely keeping three dimensions in their lanes.

The cost

O(n·m·k) — 10×10×10 = 1,000 multiply-adds here. The same loop at 1000×1000 is a billion operations, which is why libraries (BLAS) exist: same math, rearranged memory.

Where it goes wrong

  • Swapping roles in the inner product: A[t][i] or B[j][t] compile fine and are wrong. The hinge is A[i][t] * B[t][j] — row of A, column of B.
  • Trusting zero-initialized globals: on this engine global arrays are not zeroed, so C[i][j] = 0; inside the loop is mandatory, not stylistic.
  • Output discipline: separator before every value except the first of each row, newline after — the judge compares characters, not intentions.

Next step

You now hold the whole 2D trio: summing (Sum a Matrix), reindexing (Matrix Transpose), combining (this). The next grid skill asks questions about rectangles: 2D Range Sums.

Two things to remember

  • C[i][j] = Σ A[i][t]·B[t][j] — the shared m is why it is defined.
  • Zero accumulator cells explicitly; never trust a global array to start clean.
🐞 This version fails — open it and try

Inner loop runs to k instead of m — only square tests would forgive it

#include <iostream>
using namespace std;

int A[12][12], B[12][12], C[12][12];

int main() {
    int n, m, k;
    cin >> n >> m >> k;
    for (int i = 0; i < n; i++) for (int j = 0; j < m; j++) cin >> A[i][j];
    for (int i = 0; i < m; i++) for (int j = 0; j < k; j++) cin >> B[i][j];
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < k; j++) {
            C[i][j] = 0;
            for (int t = 0; t < k; t++) {   // bug: k instead of m
                C[i][j] += A[i][t] * B[t][j];
            }
        }
    }
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < k; j++) {
            cout << C[i][j];
            if (j < k - 1) cout << " ";
        }
        cout << endl;
    }
    return 0;
}