#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
long long ans;
void work(vector<string> str)
{
	int n = str.size(), m = str[0].size();
	if (n < m) {
		vector<string> tmp(m, string(n, '#'));
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				tmp[j][i] = str[i][j];
			}
		}
		str = tmp;
		swap(n, m);
	}
	if (m == 1) {
		int sum = 0;
		for (int i = 0; i < n; i++) {
			if (str[i][0] == '#') {
				sum = 0;
				continue;
			}
			ans += sum * (str[i][0] - '0');
			sum += str[i][0] - '0';
		}
		return;
	}
	int hu = n >> 1, hd = n - hu;
	vector<string> up, down;
	for (int i = 0; i < hu; i++) {
		up.push_back(str[i]);
	}
	for (int i = hu; i < n; i++) {
		down.push_back(str[i]);
	}
	work(up);
	work(down);
	up.push_back(down[0]);
	vector<vector<int> > left(hd, vector<int>(m, INF)), right(hd, vector<int>(m, -INF));
	for (int i = 0; i < m; i++) {
		if (down[0][i] != '#') {
			left[0][i] = right[0][i] = i;
		}
	}
	for (int i = 0; i < hd; i++) {
		for (int j = 0; j < m; j++) {
			if (down[i][j] == '#') {
				continue;
			}
			if (i) {
				left[i][j] = min(left[i][j], left[i - 1][j]);
				right[i][j] = max(right[i][j], right[i - 1][j]);
			}
			if (j) {
				left[i][j] = min(left[i][j], left[i][j - 1]);
				right[i][j] = max(right[i][j], right[i][j - 1]);
			}
		}
	}
	vector<vector<int> > tmp_u(hu + 1, vector<int>(m, INF));
	for (int i = 0; i <= hu; i++) {
		for (int j = 0; j < m; j++) {
			if (up[i][j] == '#') {
				continue;
			}
			tmp_u[i][j] = i;
			if (i) {
				tmp_u[i][j] = min(tmp_u[i][j], tmp_u[i - 1][j]);
			}
			if (j) {
				tmp_u[i][j] = min(tmp_u[i][j], tmp_u[i][j - 1]);
			}
		}
	}
	vector<int> top = tmp_u[hu];
	vector<vector<int> > tmp_d(hd, vector<int>(m, -INF));
	for (int i = hd - 1; i >= 0; i--) {
		for (int j = m - 1; j >= 0; j--) {
			if (down[i][j] == '#') {
				continue;
			}
			tmp_d[i][j] = i;
			if (i != hd - 1) {
				tmp_d[i][j] = max(tmp_d[i][j], tmp_d[i + 1][j]);
			}
			if (j != m - 1) {
				tmp_d[i][j] = max(tmp_d[i][j], tmp_d[i][j + 1]);
			}
		}
	}
	vector<int> bottom = tmp_d[0];
	vector<vector<int> > mn(m, vector<int>(m, INF));
	for (int i = 0; i < hd; i++) {
		for (int j = 0; j < m; j++) {
			if (left[i][j] <= right[i][j]) {
				mn[left[i][j]][right[i][j]] = min(mn[left[i][j]][right[i][j]], i);
			}
		}
	}
	for (int i = 0; i < m; i++) {
		for (int j = m - 1; j >= i; j--) {
			if (i) {
				mn[i][j] = min(mn[i][j], mn[i - 1][j]);
			}
			if (j != m - 1) {
				mn[i][j] = min(mn[i][j], mn[i][j + 1]);
			}
		}
	}
	vector<int> sum1(hd, 0);
	vector<vector<int> > sum2(hd, vector<int>(m, 0));
	vector<vector<int> > sum3(hd, vector<int>(m, 0));
	vector<vector<int> > sum4(m, vector<int>(m, 0));
	for (int i = 0; i < hd; i++) {
		if (i) {
			sum1[i] = sum1[i - 1];
			sum2[i] = sum2[i - 1];
			sum3[i] = sum3[i - 1];
		}
		for (int j = 0; j < m; j++) {
			if (left[i][j] > right[i][j]) {
				continue;
			}
			int x = down[i][j] - '0';
			sum1[i] += x;
			if (left[i][j]) {
				sum2[i][left[i][j] - 1] += x;
			}
			if (right[i][j] != m - 1) {
				sum3[i][right[i][j] + 1] += x;
			}
			if (left[i][j] && right[i][j] != m - 1) {
				sum4[left[i][j] - 1][right[i][j] + 1] += x;
			}
		}
	}
	for (int i = 0; i < hd; i++) {
		for (int j = m - 1; j; j--) {
			sum2[i][j - 1] += sum2[i][j];
		}
		for (int j = 1; j < m; j++) {
			sum3[i][j] += sum3[i][j - 1];
		}
	}
	for (int i = m - 1; i >= 0; i--) {
		for (int j = i; j < m; j++) {
			if (i != m - 1) {
				sum4[i][j] += sum4[i + 1][j];
			}
			if (j) {
				sum4[i][j] += sum4[i][j - 1];
			}
			if (i != m - 1 && j) {
				sum4[i][j] -= sum4[i + 1][j - 1];
			}
		}
	}
	auto calc = [&] (int l, int r, int lim) {
		int x = mn[l][r];
		lim = min(lim, bottom[l]);
		lim = min(lim, bottom[r]);
		if (x > lim) {
			return 0;
		}
		return sum1[lim] - sum2[lim][l] - sum3[lim][r] + sum4[l][r];
	};
	vector<vector<int> > eve(hu);
	vector<int> lp(m, INF), rp(m, -INF), can(m), del(m, false);
	for (int i = m - 1; i >= 0; i--) {
		can[i] = calc(i, i, INF);
		if (top[i] >= hu) {
			del[i] = true;
		} else {
			eve[top[i]].push_back(i);
		}
		if (down[0][i] == '#') {
			continue;
		}
		lp[i] = rp[i] = i;
		if (i != m - 1) {
			lp[i] = min(lp[i], lp[i + 1]);
			rp[i] = max(rp[i], rp[i + 1]);
		}
	}
	for (int i = hu - 1; i >= 0; i--) {
		for (int j = m - 1; j >= 0; j--) {
			if (up[i][j] == '#') {
				lp[j] = INF;
				rp[j] = -INF;
			} else if (j != m - 1) {
				lp[j] = min(lp[j], lp[j + 1]);
				rp[j] = max(rp[j], rp[j + 1]);
			}
		}
		int sum = 0, l = 0, r = -1, tp = 0;
		vector<int> que, val(m, 0);
		for (int j = 0; j < m; j++) {
			if (lp[j] > rp[j]) {
				continue;
			}
			while (r < rp[j]) {
				if (del[++r]) {
					continue;
				}
				if (tp < que.size()) {
					sum -= val[que.back()];
					val[que.back()] -= calc(que.back(), r, 1e9);
					sum += val[que.back()];
					if (bottom[que.back()] <= bottom[r]) {
						int lst = que.back();
						que.pop_back();
						while (tp < que.size()) {
							sum -= val[que.back()];
							val[que.back()] -= calc(que.back(), r, 1e9) - calc(que.back(), r, bottom[lst]);
							sum += val[que.back()];
							if (bottom[que.back()] > bottom[r]) {
								break;
							}
							lst = que.back();
							que.pop_back();
						}
					}
				}
				que.push_back(r);
				val[r] = can[r];
				sum += val[r];
			}
			while (l < lp[j]) {
				if (del[l]) {
					l++;
					continue;
				}
				sum -= val[l];
				while (tp < que.size() && que[tp] == l) {
					tp++;
				}
				l++;
			}
			ans += (up[i][j] - '0') * sum;
		}
		for (int x : eve[i]) {
			del[x] = true;
		}
	}
}
int main()
{
	int n;
	cin >> n;
	vector<string> str(n);
	for (int i = 0; i < n; i++) {
		cin >> str[i];
	}
	work(str);
	cout << ans << endl;
	return 0;
}

Measured memory_bytes: 50008