#include #define show(x) cerr << #x << " = " << x << endl using namespace std; using ll = long long; using pii = pair; using vi = vector; template ostream& operator<<(ostream& os, const vector& v) { os << "sz=" << v.size() << "\n["; for (const auto& p : v) { os << p << ","; } os << "]\n"; return os; } template ostream& operator<<(ostream& os, const pair& p) { os << "(" << p.first << "," << p.second << ")"; return os; } constexpr ll MOD = 1e9 + 7; template constexpr T INF = numeric_limits::max() / 100; void concat(vector>& table, const vector>& f, const vector>& l, const vector>& A) { const int m = f.size(); for (int m1 = 0; m1 < m; m1++) { for (int m2 = 0; m2 < m; m2++) { for (int m3 = 0; m3 < m; m3++) { for (int m4 = 0; m4 < m; m4++) { table[m1][m4] = max(table[m1][m4], f[m1][m2] + l[m3][m4] + A[m2][m3]); } } } } } int main() { cin.tie(0); ios::sync_with_stdio(false); ll n, m; cin >> n >> m; vector> A(m, vector(m, 0)); for (ll i = 0; i < m; i++) { for (ll j = 0; j < m; j++) { cin >> A[i][j]; } } constexpr int MAX = 35; vector>> dp(MAX, vector>(m, vector(m, -INF))); //dp[i][m1][m2] = 長さ2^iでm1から始まりm2で終わる譜面のmax for (int i = 0; i < m; i++) { dp[0][i][i] = 0; } for (int i = 1; i < MAX; i++) { concat(dp[i], dp[i - 1], dp[i - 1], A); } vector len; for (int i = 0; i < MAX; i++) { if (n & (1LL << i)) { len.push_back(i); } } vector> table(m, vector(m)); for (int i = 0; i < len.size(); i++) { if (i == 0) { table = dp[len[i]]; } else { vector> emp(m, vector(m, 0)); concat(emp, table, dp[len[i]], A); table = emp; } } ll maxi = 0; for (int i = 0; i < m; i++) { for (int j = 0; j < m; j++) { maxi = max(maxi, table[i][j]); } } cout << maxi << endl; return 0; }