#include <bits/stdc++.h>
using namespace std;

using ll = long long;
using vl = vector<ll>;
using vi = vector<int>;

#define rng(i, a, b) for(int i = (a); i < (b); ++i)
#define rep(n) for(int _ = 0, __ = (int)n; _ < __; _++)
#define stp(i, a, b, c) for (int i = (a); i < (b); i += (c))
#define FOR(x, cont) for (auto &x: cont)
#define all(x) (x).begin(), (x).end()
#define pb push_back
#define eb emplace_back
#define SZ(x) (int)(x).size()
#define pq(T,COMP) priority_queue<T, vector<T>, COMP>
auto bet = [](const ll x, const ll y, const ll i) {
    return x <= i && i <= y;
};
using pii = pair<int,int>;
using vb = vector<bool>;

vi get_prime(int n) {
    vi minp(n+1);
    vi p;
    for (int i = 2; i <= n; i++) {
        if (!minp[i]) {
            minp[i] = i;
            p.pb(i);
        }
        FOR(x, p) {
            if (x <= minp[i] && x * i <= n)
                minp[x * i] = x;
        }
    }
    return p;
}

const int mod = 1e9 + 7;

void add_mod(ll &x, const ll &y) {
    x += y;
    if (x >= mod) x -= mod;
}
void sub_mod(ll &x, const ll &y) {
    x -= y;
    if (x < 0) x += mod;
}


// AGC028 F Reachable Cells
// 不能O(1)转移，考虑O(n)转移
// 理解 tourist 代码 https://agc028.contest.atcoder.jp/submissions/3398112
// L[i][j][k]:从(i,j)能走到的第k行的最左端是列的编号（k >= i）
// R[i][j][k]:.....................右..................
// L[i][j][k]:初始值为n
// R[i][j][k]:初始值为0
// 需要注意的是：并不是L[i][j][k]和R[i][j][k]之间所有的非'#'点都是可以到达的。
const int N = 505;
int L[N][N][N], R[N][N][N];
int row[N][N];

int main() {
#ifdef LOCAL
    freopen("main.in", "r", stdin);
#endif
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n;
    vector<string> b(n);
    rng (i, 0, n) cin >> b[i];
    vector<vector<int>> a(n, vector<int>(n));

    for (int i = 0; i < n; i++) {
        for (int j = 0; j < n; j++) {
            a[i][j] = b[i][j] == '#' ? 0 : b[i][j] - '0';
        }
    }

    for (int i = 0; i < n; i++) {
        int sum = 0;
        for (int j = 0; j < n; j++) {
            sum += a[i][j];
            row[i][j] = sum;
        }
    }

    ll ans = 0;
    function<void(int,int)> put=[&](int x, int y) {
        if (x >= 0 && x < n && y >= 0 && y < n && a[x][y] > 0) {
            // 若某个点上边被堵住了，左边也被堵住了，那么对于这个点左上侧的点来说，这个点是不可到达的
            if (x == 0 || a[x-1][y] == 0)
                if (y == 0 || a[x][y - 1] == 0) {
                    rng (k, y, n) row[x][k] -= a[x][y];
                    a[x][y] = 0;
                    put(x + 1, y);
                    put(x, y + 1);
                }
        }
    };

    for (int i = n - 1; i >= 0; --i) {
        for (int j = n -1 ; j >= 0; --j) {
            if (a[i][j] > 0) {
//                cout <<"POINT: " << i << ' ' << j << endl;
                // 初始化
                rng(k, i, n) {
                    L[i][j][k] = n;
                    R[i][j][k] = 0;
                }
                L[i][j][i] = j;
                R[i][j][i] = j;
                // end 初始化
                if (i < n - 1 && a[i + 1][j] > 0) {
                    rng (k, i + 1, n) {
                        L[i][j][k] = min(L[i][j][k], L[i + 1][j][k]);
                        R[i][j][k] = max(R[i][j][k], R[i + 1][j][k]);
                    }
                }
                if (j < n - 1 && a[i][j + 1] > 0) {
                    rng (k, i, n) {
                        L[i][j][k] = min(L[i][j][k], L[i][j + 1][k]);
                        R[i][j][k] = max(R[i][j][k], R[i][j + 1][k]);
                    }
                }
                int sum = 0;
                rng (k, i, n) {
                    if (L[i][j][k] <= R[i][j][k]) {
//                        cout << k << ": " << L[i][j][k] << ' ' << R[i][j][k] << endl;
                        sum += L[i][j][k] == 0 ? row[k][R[i][j][k]] : row[k][R[i][j][k]] - row[k][L[i][j][k] - 1];
                    }
                }
                ans += a[i][j] * (sum - a[i][j]);
//                cout << "ans: " << ans << endl;
                put(i, j);
            }
        }
    }

    cout << ans << '\n';


    return 0;
}

Measured memory_bytes: 1000960