#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;
}