#pragma GCC optimize("O3,inline")
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
#define int ll
using ii = pair<int, int>;
using iii = pair<int, ii>;
using pvii = pair<vector<int>, ii>;
constexpr int MAXN = 20000 + 5;
constexpr int INF = 1e18 + 5;
constexpr int LOG = 20;
signed main() {
ios_base::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr);
int N, M, K; cin >> N >> M >> K;
int ans = N * M;
vector<pvii> inp(N);
for (int i = 0; i < N; ++i) {
vector<int> lol(M); for (int j = 0; j < M; ++j) cin >> lol[j];
sort(lol.begin(), lol.end());
int s = 0; for (int j = 0; j < M; ++j) s += lol[j];
inp[i] = pvii{lol, ii{s, i}};
}
sort(inp.begin(), inp.end(), [&](const pvii &a, const pvii &b) {
return a.second.first < b.second.first || a.second.first == b.second.first && a.second.second > b.second.second;
});
int prevMax = 0;
for (int i = 0; i < N; ++i) {
int nextVal = (i == N-1 ? K * M : inp[i+1].second.first);
vector<int> &v = inp[i].first;
int s = inp[i].second.first;
int idx = inp[i].second.second;
int lastIdx = (i ? inp[i-1].second.second : INF);
if (idx > lastIdx) prevMax++;
int remCtr1 = 0;
int ps = s;
for (int j = 0; j < M; ++j) {
if (ps - v[j] >= prevMax) {
ps -= v[j]; remCtr1++;
}
}
int remCtr2 = 0;
ps = s;
for (int j = M-1; j >= 0; --j) {
if (ps - v[j] + K <= nextVal) {
ps = ps - v[j] + K; remCtr2++;
}
}
int maxRem = min(remCtr1, remCtr2);
if (!maxRem) {
prevMax = s;
//cout << "0" << '\n';
continue;
}
vector<bitset<10005>> dp_prev(maxRem + 1);
vector<bitset<10005>> dp_curr(maxRem + 1);
dp_curr[0].set(0);
for (int j = 0; j < M; ++j) {
swap(dp_curr, dp_prev);
for (int k = 0; k <= maxRem; ++k) dp_curr[k] = dp_prev[k] << v[j];
for (int k = 1; k <= maxRem; ++k) dp_curr[k] |= dp_prev[k-1];
}
[&]() {
for (int k = maxRem; k > 0; --k) {
for (int j = prevMax; j <= nextVal - k * K; ++j) {
if (dp_curr[k][j]) {
ans -= k;
//cout << k << ' ' << j << '\n';
prevMax = j + k * K;
return;
}
}
}
prevMax = s;
//cout << "0" << '\n';
}();
}
cout << ans;
}