#include <iostream>
#include <vector>
using namespace std;


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

    // 首先判断是否存在可能的摆放方式
    // 要使得任意行、列至少有一个小球,那么小球总数至少为 max(n, m)(当 n 和 m 中较大的那个作为基础,每行每列至少一个)
    // 同时小球总数不能超过 n * m(因为每个格子最多放 k 个,但这里只要存在一种方式,所以先考虑总数不超过 n*m 即可,因为可以分散放置)
    if (k < max(n, m)) {
        cout << -1 << endl;
        return 0;
    }

    // 构建结果矩阵
    vector<vector<long long>> result(n, vector<long long>(m, 0));

    // 先在主对角线上放置小球,保证每行每列至少一个
    long long count = 0;
    for (long long i = 0; i < min(n, m); ++i) {
        result[i][i] = 1;
        count++;
    }

    // 如果主对角线长度不够(比如 n 和 m 不相等),继续在剩余行或列补充
    if (n > m) {
        for (long long i = m; i < n; ++i) {
            result[i][0] = 1;
            count++;
        }
    }
    else if (m > n) {
        for (long long j = n; j < m; ++j) {
            result[0][j] = 1;
            count++;
        }
    }

    // 现在已经保证了每行每列至少有一个小球,接下来分配剩余的小球
    long long remaining = k - count;
    for (long long i = 0; i < n && remaining > 0; ++i) {
        for (long long j = 0; j < m && remaining > 0; ++j) {
            result[i][j] += remaining;
            remaining = 0;
        }
    }

    // 输出结果矩阵
    for (long long i = 0; i < n; ++i) {
        for (long long j = 0; j < m; ++j) {
            cout << result[i][j] << " ";
        }
        cout << endl;
    }

    return 0;
}