#include <bits/stdc++.h>   using namespace std;   template <typename T>   ostream& operator<<(ostream& out, const vector<T>& v) {     out <<  [ ;     for (auto vi : v) out << vi <<  ,  ;     out <<  ] n ;     return out;   }   const int MAX_N = 1024;   const int MOD = 1e9 + 7;   struct RSQ {     static const int len = 1024;     vector<double> a = vector<double>(len * 2 + 1, 0.0);     void add(int i, double value, int node = 1, int l = 0, int r = len - 1) {       if (l <= i && i <= r) {         a[node] += value;         if (l < r) {           int m = (l + r) / 2;           add(i, value, node * 2, l, m);           add(i, value, node * 2 + 1, m + 1, r);         }       }     }     double sum(int ql, int qr, int node = 1, int l = 0, int r = len - 1) {       if (ql <= l && r <= qr) {         return a[node];       } else if (qr < l || r < ql) {         return 0;       } else {         int m = (l + r) / 2;         return sum(ql, qr, node * 2, l, m) + sum(ql, qr, node * 2 + 1, m + 1, r);       }     }   };   int n;   vector<vector<int> > a(MAX_N, vector<int>(MAX_N));   vector<vector<vector<int> > > _len2zero(       MAX_N, vector<vector<int> >(MAX_N, vector<int>(8, -1)));   const int DX[] = {-1, -1, 0, +1, +1, +1, 0, -1};   const int DY[] = {0, +1, +1, +1, 0, -1, -1, -1};   int len2zero(int x, int y, int dir) {     if (!(0 <= x && x < n && 0 <= y && y < n) || a[x][y] == 0) {       return 0;     }     int& res = _len2zero[x][y][dir];     if (res == -1) {       res = 1 + len2zero(x + DX[dir], y + DY[dir], dir);     }     return res;   }   RSQ sumLine[MAX_N * 2], sumColumn[MAX_N * 2], sumMainD[MAX_N * 2],       sumMinorD[MAX_N * 2];   long long solution() {     vector<double> ln({-1, log(1.0), log(2.0), log(3.0)});     for (int x = 0; x < n; x++) {       for (int y = 0; y < n; y++) {         sumLine[x].add(y, ln[a[x][y]]);         sumColumn[y].add(x, ln[a[x][y]]);         sumMainD[n + x - y].add(x, ln[a[x][y]]);         sumMinorD[x + y].add(x, ln[a[x][y]]);       }     }     tuple<double, int, int, int, bool> best;     for (int x = 0; x < n; x++) {       for (int y = 0; y < n; y++) {         int d = 100500;         for (int dir : {0, 2, 4, 6}) {           d = min(d, len2zero(x, y, dir));         }         if (d) d--;         double logSum = sumLine[x].sum(y - d, y + d) +                         sumColumn[y].sum(x - d, x + d) - ln[a[x][y]];         if (logSum > get<0>(best)) {           best = make_tuple(logSum, x, y, d, true);         }         d = 100500;         for (int dir : {1, 3, 5, 7}) {           d = min(d, len2zero(x, y, dir));         }         if (d) d--;         logSum = sumMainD[n + x - y].sum(x - d, x + d) +                  sumMinorD[x + y].sum(x - d, x + d) - ln[a[x][y]];         if (logSum > get<0>(best)) {           best = make_tuple(logSum, x, y, d, false);         }       }     }     double temp;     int x, y, d;     bool isNormal;     tie(temp, x, y, d, isNormal) = best;     long long result = a[x][y];     if (isNormal) {       for (int dd = 1; dd <= d; dd++) {         for (int dir : {0, 2, 4, 6}) {           result *= a[x + DX[dir] * dd][y + DY[dir] * dd];           result %= MOD;         }       }     } else {       for (int dd = 1; dd <= d; dd++) {         for (int dir : {1, 3, 5, 7}) {           result *= a[x + DX[dir] * dd][y + DY[dir] * dd];           result %= MOD;         }       }     }     return result;   }   void readData() {     cin >> n;     for (int i = 0; i < n; i++) {       string s;       cin >> s;       assert(s.size() == n);       for (int j = 0; j < (int)s.size(); j++) {         a[i][j] = s[j] -  0 ;       }     }   }   int main() {     ios::sync_with_stdio(false);     readData();     cout << solution() <<   n ;     return 0;   }