Problem: Problem F and F2 are the same problem, but with different constraints and time limits.

We have a board divided into N horizontal rows and N vertical columns of square cells. The cell at the i-th row from the top and the j-th column from the left is called Cell (i,j). Each cell is either empty or occupied by an obstacle. Also, each empty cell has a digit written on it. If A_{i,j}= `1`, `2`, ..., or `9`, Cell (i,j) is empty and the digit A_{i,j} is written on it. If A_{i,j}= `#`, Cell (i,j) is occupied by an obstacle.

Cell Y is reachable from cell X when the following conditions are all met:

* Cells X and Y are different.
* Cells X and Y are both empty.
* One can reach from Cell X to Cell Y by repeatedly moving right or down to an adjacent empty cell.



Consider all pairs of cells (X,Y) such that cell Y is reachable from cell X. Find the sum of the products of the digits written on cell X and cell Y for all of those pairs.

Constraints

* 1 \leq N \leq 500
* A_{i,j} is one of the following characters: `1`, `2`, ... `9` and `#`.

Input

Input is given from Standard Input in the following format:


N
A_{1,1}A_{1,2}...A_{1,N}
A_{2,1}A_{2,2}...A_{2,N}
:
A_{N,1}A_{N,2}...A_{N,N}


Output

Print the sum of the products of the digits written on cell X and cell Y for all pairs (X,Y) such that cell Y is reachable from cell X.

Examples

Input

2
11
11


Output

5


Input

4
1111
11#1
1#11
1111


Output

47


Input

10
76##63##3#
8445669721
75#9542133
3#285##445
749632##89
2458##9515
5952578#77
1#3#44196#
4355#99#1#
298#63587


Output

36065


Input

10
4177143673
7#########
5#1716155#
6#4#####5#
2#3#597#6#
6#9#8#3#5#
5#2#899#9#
1#6#####6#
6#5359657#
5#########


Output

6525

Solution (in CPP):

Solution:
//無理。

#include <bits/stdc++.h>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n - 1); }
template<class T> using V = vector<T>;
template<class T> using VV = V<V<T>>;

const int MN = 550;
int N;
using B = array<ull, MN/64+1>;
int g[MN][MN];


B used[MN][MN];

namespace std {
bool operator<(const B &l, const B &r) {
    for (int i = 0; i < MN / 64 + 1; i++) {
        if (l[i] != r[i]) return l[i] < r[i];
    }
    return false;
}
bool operator>(const B &l, const B &r) {
    return r < l;
}

bool operator==(const B &l, const B &r) {
    for (int i = 0; i < MN / 64 + 1; i++) {
        if (l[i] != r[i]) return false;
    }
    return true;
}
}

bool sam(const B& l, const B& r) {
    for (int i = 0; i < MN/64+1; i++) {
        if (l[i] & r[i]) return true;
    }
    return false;
}

bool gt(const B& b, int id) {
    return (b[id/64] & (1ULL << (id%64))) != 0;
}

void st(B& b, int id) {
    b[id/64] |= 1ULL << (id % 64);
}

int L, R, D, U;
void dfs_up(int a, int b, int id) {
    if (!(L <= a && a <= R && D <= b && b <= U)) return;
    //if (g[a][b] == 0 || used[a][b][id]) return;
    if (g[a][b] == 0 || gt(used[a][b], id)) return;
    st(used[a][b], id);
    //used[a][b][id] = true;
    dfs_up(a-1, b, id); dfs_up(a, b-1, id);
}

void dfs_dw(int a, int b, int id) {
    if (!(L <= a && a <= R && D <= b && b <= U)) return;
    if (g[a][b] == 0 || gt(used[a][b], id)) return;
    st(used[a][b], id);
//    if (g[a][b] == 0 || used[a][b][id]) return;
//    used[a][b][id] = true;
    dfs_dw(a+1, b, id); dfs_dw(a, b+1, id);
}

ll ans = 0;

using P = pair<B, int>;

V<P> uni(V<P> v) {
    sort(v.begin(), v.end());
    V<P> res;
    for (auto &p: v) {
        if (res.size() && res.back().first == p.first) {
            res.back().second += p.second;
            continue;
        }
        res.push_back(p);
    }
    return res;
}
void solve(int l, int r, int d, int u) {
    if (r < l || u < d) return;
    if (l == r && d == u) return;
    L = l; R = r; D = d; U = u;
    for (int x = l; x <= r; x++) {
        for (int y = d; y <= u; y++) {
            used[x][y] = B();
        }
    }
    if (r-l > u-d) {
        int m = (l+r)/2;
        for (int y = d; y <= u; y++) {
            dfs_up(m, y, y);
        }
        for (int y = u; y >= d; y--) {
            dfs_dw(m+1, y, y);
        }
        V<P> mp1, mp2;
        for (int x = l; x <= r; x++) {
            for (int y = d; y <= u; y++) {
                if (x <= m) mp1.push_back(P(used[x][y], g[x][y]));
                else mp2.push_back(P(used[x][y], g[x][y]));
            }
        }
        mp1 = uni(mp1); mp2 = uni(mp2);

        for (auto &p1: mp1) {
            for (auto &p2: mp2) {
                //if ((p1.first & p2.first).count()) ans += ll(p1.second) * p2.second;
                if (sam(p1.first, p2.first)) ans += ll(p1.second) * p2.second;
            }
        }
        solve(l, m, d, u);
        solve(m+1, r, d, u);
    } else {
        int m = (d+u)/2;

        for (int x = l; x <= r; x++) {
            dfs_up(x, m, x);
        }
        for (int x = r; x >= l; x--) {
            dfs_dw(x, m+1, x);
        }

        using P = pair<B, int>;
        V<P> mp1, mp2;
        for (int x = l; x <= r; x++) {
            for (int y = d; y <= u; y++) {
                if (y <= m) mp1.push_back(P(used[x][y], g[x][y]));
                else mp2.push_back(P(used[x][y], g[x][y]));
            }
        }
        mp1 = uni(mp1); mp2 = uni(mp2);
/*        map<B, int> mp1, mp2;
        for (int x = l; x <= r; x++) {
            for (int y = d; y <= u; y++) {
                if (y <= m) mp1[used[x][y]] += g[x][y];
                else mp2[used[x][y]] += g[x][y];
            }
        }*/
        for (auto &p1: mp1) {
            for (auto &p2: mp2) {
                if (sam(p1.first, p2.first)) ans += ll(p1.second) * p2.second;
            }
        }
        solve(l, r, d, m);
        solve(l, r, m+1, u);
    }
}


int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout << setprecision(20) << fixed;
    cin >> N;
    for (int i = 1; i <= N; i++) {
        string s;
        cin >> s;
        for (int j = 1; j <= N; j++) {
            int d = 0;
            if (isdigit(s[j-1])) d = s[j-1] - '0';
            g[i][j] = d;
            //ans -= d*d;
        }
    }
    solve(1, N, 1, N);
    cout << ans << endl;
    return 0;
}