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>
#pragma GCC optimize(3)
using namespace std;
#define iinf 2000000000
#define linf 1000000000000000000LL
#define ulinf 10000000000000000000ull
#define MOD1 1000000007LL
#define mpr make_pair
typedef long long LL;
typedef unsigned long long ULL;
typedef unsigned long UL;
typedef unsigned short US;
typedef pair < int , int > pii;
clock_t __stt;
inline void TStart(){__stt=clock();}
inline void TReport(){printf("\nTaken Time : %.3lf sec\n",(double)(clock()-__stt)/CLOCKS_PER_SEC);}
template < typename T > T MIN(T a,T b){return a<b?a:b;}
template < typename T > T MAX(T a,T b){return a>b?a:b;}
template < typename T > T ABS(T a){return a>0?a:(-a);}
template < typename T > void UMIN(T &a,T b){if(b<a) a=b;}
template < typename T > void UMAX(T &a,T b){if(b>a) a=b;}
int n,g[505][505],s[505][505],mx[505];
bool e[505][505];
LL res;
int readchar(){
	char c=getchar();
	while(c==' ' || c=='\n') c=getchar();
	if(c=='#') return 0;
	return c-'0';
}
namespace DSU{
	int fa[250005],rk[250005];
	void init(){
		int i;
		memset(rk,0,sizeof(rk));
		for(i=0;i<=n*n;++i) fa[i]=i;
	}
	int ancestor(int x){
		if(fa[x]!=x) fa[x]=ancestor(fa[x]);
		return fa[x];
	}
	void unite(int u,int v){
		u=ancestor(u);
		v=ancestor(v);
		if(rk[u]<rk[v])
			fa[u]=v;
		else if(rk[u]>rk[v])
			fa[v]=u;
		else{
			fa[u]=v;
			++rk[v];
		}
	}
	bool con(int u,int v){
		return ancestor(u)==ancestor(v);
	}
};
void add(int x,int y){
	e[x][y]=1;
	if(e[x-1][y]) DSU::unite(x*n+y,(x-1)*n+y);
	if(e[x][y-1]) DSU::unite(x*n+y-1,x*n+y);
	if(e[x+1][y]) DSU::unite(x*n+y,(x+1)*n+y);
	if(e[x][y+1]) DSU::unite(x*n+y+1,x*n+y);
	if(x<n-1 && g[x+1][y] && !e[x+1][y]) add(x+1,y);
	if(y<n-1 && g[x][y+1] && !e[x][y+1]) add(x,y+1);
}
int getlower(int x,int y){
	int cx=x,cy=y,ret=(y?s[x][y-1]:0);
	mx[y]=x;
	while(1){
		while(1){
			if(cx+1<n && e[cx+1][cy]){
				++cx;
				mx[y]=cx;
				ret+=(cy?s[cx][cy-1]:0);
			}
			else if(cy+1<n && e[cx][cy+1]){
				++cy;
			}
			else break;
		}
		bool found=0;
		while(cy+1<n){
			++cy;
			if(e[cx][cy] && DSU::con(cx*n+cy,x*n+y)){
				found=1;
				break;
			}
			else if(e[cx][cy]) break;
		}
		if(!found) break;
	}
	return ret;
}
int getupper(int x,int y){
	int cx=x,cy=y,ret=0;
	while(1){
		while(1){
			if(cy+1<n && e[cx][cy+1]){
				++cy;
			}
			else if(cx+1<n && e[cx+1][cy]){
				ret+=s[cx][cy];
				++cx;
			}
			else break;
		}
		bool found=0;
		while(cx<n-1){
			ret+=s[cx][cy];
			++cx;
			if(cx>mx[y]) break;
			if(e[cx][cy] && DSU::con(cx*n+cy,x*n+y)){
				found=1;
				break;
			}
			else if(e[cx][cy]) break;
		}
		if(!found || cx>mx[y]) break;
	}
	if(cx<=mx[y]) ret+=s[cx][cy];
	return ret;
}
void solveline(int x){
	int i,j,k;
	memcpy(s,g,sizeof(g));
	for(i=0;i<n;++i){
		for(j=1;j<n;++j){
			s[i][j]+=s[i][j-1];
		}
	}
	DSU::init();
	for(i=x;i<n;++i) memset(e[i],0,sizeof(e[i]));
	for(i=0;i<n;++i){
		if(!g[x][i]) continue;
		add(x,i);
		res-=(LL)g[x][i]*(LL)getlower(x,i);
	}
	DSU::init();
	for(i=x;i<n;++i) memset(e[i],0,sizeof(e[i]));
	for(i=n-1;i>=0;--i){
		if(!g[x][i]) continue;
		add(x,i);
		res+=(LL)g[x][i]*(LL)(getupper(x,i)-g[x][i]);
	}
}
void del(int x,int y){
	if((!x || !g[x-1][y]) && (!y || !g[x][y-1])){
		g[x][y]=0;
		if(x<n-1 && g[x+1][y]) del(x+1,y);
		if(y<n-1 && g[x][y+1]) del(x,y+1);
	}
}
int main(){
    // inputting start
    // 数据结构记得初始化！ n，m别写反！
    int i,j,k;
	scanf("%d",&n);
	for(i=0;i<n;++i){
		for(j=0;j<n;++j){
			g[i][j]=readchar();
		}
	}
    #ifdef LOCAL
        TStart();
    #endif
    // calculation start
    // 数据结构记得初始化！ n，m别写反！
	for(i=0;i<n;++i){
		for(j=0;j<n;++j){
			e[i][j]=(!!g[i][j]);
		}
	}
    for(i=n-1;i>=0;--i){
		solveline(i);
		for(j=0;j<n;++j){
			if(g[i][j]) del(i,j);
		}
	}
	printf("%lld\n",res);
    #ifdef LOCAL
        TReport();
    #endif
    return 0;
}