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

using ll=long long;
#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))

using uint=unsigned;
using ull=unsigned long long;

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

void print(ll x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<endl;
	#else
	cout<<"Yes"<<endl;
	#endif
	if(ex)exit(0);
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<endl;
	#else
	cout<<"No"<<endl;
	#endif
	if(ex)exit(0);
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
int mask(int i){
	return (int(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
    static random_device rd;
    static mt19937_64 gen(rd());
    #endif
    return uniform_int_distribution<ll>(l, r)(gen);
}

void imp(){
	cout<<0<<endl;
	exit(0);
}

using uint=unsigned;
using ull=unsigned long long;

//initfact();
const uint mod=998244353;
//const uint mod=1000000007;
//uint mod=1;
struct mint{
	uint v;
	mint(ll vv=0){s(vv%mod+mod);}
	mint& s(uint vv){
		v=vv<mod?vv:vv-mod;
		return *this;
	}
	mint operator-()const{return mint()-*this;}
	mint& operator+=(const mint&rhs){return s(v+rhs.v);}
	mint&operator-=(const mint&rhs){return s(v+mod-rhs.v);}
	mint&operator*=(const mint&rhs){
		v=ull(v)*rhs.v%mod;
		return *this;
	}
	mint&operator/=(const mint&rhs){return *this*=rhs.inv();}
	mint operator+(const mint&rhs)const{return mint(*this)+=rhs;}
	mint operator-(const mint&rhs)const{return mint(*this)-=rhs;}
	mint operator*(const mint&rhs)const{return mint(*this)*=rhs;}
	mint operator/(const mint&rhs)const{return mint(*this)/=rhs;}
	mint pow(int n)const{
		mint res(1),x(*this);
		while(n){
			if(n&1)res*=x;
			x*=x;
			n>>=1;
		}
		return res;
	}
	mint inv()const{return pow(mod-2);}
	/*mint inv()const{
		int x,y;
		int g=extgcd(v,mod,x,y);
		assert(g==1);
		if(x<0)x+=mod;
		return mint(x);
	}*/
	friend ostream& operator<<(ostream&os,const mint&m){
		return os<<m.v;
	}
	bool operator<(const mint&r)const{return v<r.v;}
	bool operator==(const mint&r)const{return v==r.v;}
};

const int vmax=(1<<21)+10;
mint fact[vmax],finv[vmax],invs[vmax];
void initfact(){
	fact[0]=1;
	rng(i,1,vmax){
		fact[i]=fact[i-1]*i;
	}
	finv[vmax-1]=fact[vmax-1].inv();
	for(int i=vmax-2;i>=0;i--){
		finv[i]=finv[i+1]*(i+1);
	}
	for(int i=vmax-1;i>=1;i--){
		invs[i]=finv[i]*fact[i-1];
	}
}
mint choose(int n,int k){
	return fact[n]*finv[n-k]*finv[k];
}
mint binom(int a,int b){
	return fact[a+b]*finv[a]*finv[b];
}
mint catalan(int n){
	return binom(n,n)-(n-1>=0?binom(n-1,n+1):0);
}

void dfs(int v,vi&vis,int&vn,int&ec,int&nc,const vvc<int>&g,const vi&need){
	assert(vis[v]==0);
	vis[v]=1;
	vn++;
	nc^=need[v];
	for(auto to:g[v]){
		if(vis[to]==0){
			dfs(to,vis,vn,ec,nc,g,need);
		}else if(vis[to]==1){
			ec++;
		}
	}
	vis[v]=2;
}

mint slv(int n,vc<tuple<ll,ll,ll>> es){
	if(n%2==0)return mint(2).pow(n*(n-1)/2-es.size());
	vi need(n);
	vvc<int> g(n,vi(n,1));
	for(auto e:es){
		ll a,b,c;tie(a,b,c)=e;
		need[a]^=c;
		need[b]^=c;
		g[a][b]=0;
		g[b][a]=0;
	}
	vvc<int> h(n);
	rep(i,n)rep(j,n)if(i!=j)if(g[i][j])
		h[i].pb(j);
	vi vis(n);
	mint ans=1;
	rep(i,n)if(vis[i]==0){
		int vn=0,ec=0,nc=0;
		dfs(i,vis,vn,ec,nc,h,need);
		if(nc)imp();
		ans*=mint(2).pow(ec-vn+1);
	}
	return ans;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);
	
	int n;cin>>n;n--;
	vc<string> s(n);
	rep(i,n)cin>>s[i];
	
	rep(i,n)rng(j,i+1,n)if(s[i][j]!='?'){
		if(s[j][i]!='?'&&s[j][i]!=s[i][j]){
			imp();
		}
		s[j][i]=s[i][j];
	}
	
	rep(i,n)rng(j,n-i,n)if(s[i][j]!='?'){
		if(s[n-1-j][n-1-i]!='?'&&s[n-1-j][n-1-i]!=s[i][j]){
			imp();
		}
		s[n-1-j][n-1-i]=s[i][j];
	}
	
	int z=n+2;
	
	vi tp(z);
	rep(i,z)
		if(i<z-1&&i%2==0)tp[i]=1;
	
	vi vs[2];
	rep(i,z)
		vs[tp[i]].pb(i);
	
	vc<tuple<int,int,int>> es[2];
	
	rep(i,n)rep(j,min(i,n-1-i)+1)if(s[i][j]!='?'){
		int x=i+j+1;
		int y=i-j-1;
		if(y==-1)y=n+1;
		assert(tp[x]==tp[y]);
		int t=tp[x];
		x=lower_bound(all(vs[t]),x)-vs[t].bg;
		y=lower_bound(all(vs[t]),y)-vs[t].bg;
		int w=s[i][j]=='o';
		es[t].eb(x,y,w);
	}
	
	mint ans=1;
	
	rep(k,2)
		ans*=slv(vs[k].size(),es[k]);
	cout<<ans<<endl;
}

### Prompt

Create a solution in CPP for the following problem:

In a two-dimensional plane, there is a square frame whose vertices are at coordinates (0,0), (N,0), (0,N), and (N,N). The frame is made of mirror glass. A ray of light striking an edge of the frame (but not a vertex) will be reflected so that the angle of incidence is equal to the angle of reflection. A ray of light striking a vertex of the frame will be reflected in the direction opposite to the direction it is coming from.

We will define the path for a grid point (a point with integer coordinates) (i,j) (0<i,j<N) strictly within the frame, as follows:

* The path for (i,j) is the union of the trajectories of four rays of light emitted from (i,j) to (i-1,j-1), (i-1,j+1), (i+1,j-1), and (i+1,j+1).



<image>

Figure: an example of a path for a grid point

There is a light bulb at each grid point strictly within the frame. We will assign a state - ON or OFF - to each bulb. The state of the whole set of bulbs are called beautiful if it is possible to turn OFF all the bulbs by repeating the following operation:

* Choose a grid point strictly within the frame, and switch the states of all the bulbs on its path.



Takahashi has set the states of some of the bulbs, but not for the remaining bulbs. Find the number of ways to set the states of the remaining bulbs so that the state of the whole set of bulbs is beautiful, modulo 998244353. The state of the bulb at the grid point (i,j) is set to be ON if A_{i,j}=`o`, OFF if A_{i,j}=`x`, and unset if A_{i,j}=`?`.

Constraints

* 2 \leq N \leq 1500
* A_{ij} is `o`, `x`, or `?`.

Input

Input is given from Standard Input in the following format:


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


Output

Print the answer.

Examples

Input

4
o?o
???
?x?


Output

1


Input

5
o?o?
????
o?x?
????


Output

0


Input

6
?o???
????o
??x??
o????
???o?


Output

32


Input

9
????o??x
?????x??
??o?o???
?o?x????
???????x
x?o?o???
????????
x?????x?


Output

4

### Response

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

using ll=long long;
#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))

using uint=unsigned;
using ull=unsigned long long;

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

void print(ll x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<endl;
	#else
	cout<<"Yes"<<endl;
	#endif
	if(ex)exit(0);
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<endl;
	#else
	cout<<"No"<<endl;
	#endif
	if(ex)exit(0);
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
int mask(int i){
	return (int(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
    static random_device rd;
    static mt19937_64 gen(rd());
    #endif
    return uniform_int_distribution<ll>(l, r)(gen);
}

void imp(){
	cout<<0<<endl;
	exit(0);
}

using uint=unsigned;
using ull=unsigned long long;

//initfact();
const uint mod=998244353;
//const uint mod=1000000007;
//uint mod=1;
struct mint{
	uint v;
	mint(ll vv=0){s(vv%mod+mod);}
	mint& s(uint vv){
		v=vv<mod?vv:vv-mod;
		return *this;
	}
	mint operator-()const{return mint()-*this;}
	mint& operator+=(const mint&rhs){return s(v+rhs.v);}
	mint&operator-=(const mint&rhs){return s(v+mod-rhs.v);}
	mint&operator*=(const mint&rhs){
		v=ull(v)*rhs.v%mod;
		return *this;
	}
	mint&operator/=(const mint&rhs){return *this*=rhs.inv();}
	mint operator+(const mint&rhs)const{return mint(*this)+=rhs;}
	mint operator-(const mint&rhs)const{return mint(*this)-=rhs;}
	mint operator*(const mint&rhs)const{return mint(*this)*=rhs;}
	mint operator/(const mint&rhs)const{return mint(*this)/=rhs;}
	mint pow(int n)const{
		mint res(1),x(*this);
		while(n){
			if(n&1)res*=x;
			x*=x;
			n>>=1;
		}
		return res;
	}
	mint inv()const{return pow(mod-2);}
	/*mint inv()const{
		int x,y;
		int g=extgcd(v,mod,x,y);
		assert(g==1);
		if(x<0)x+=mod;
		return mint(x);
	}*/
	friend ostream& operator<<(ostream&os,const mint&m){
		return os<<m.v;
	}
	bool operator<(const mint&r)const{return v<r.v;}
	bool operator==(const mint&r)const{return v==r.v;}
};

const int vmax=(1<<21)+10;
mint fact[vmax],finv[vmax],invs[vmax];
void initfact(){
	fact[0]=1;
	rng(i,1,vmax){
		fact[i]=fact[i-1]*i;
	}
	finv[vmax-1]=fact[vmax-1].inv();
	for(int i=vmax-2;i>=0;i--){
		finv[i]=finv[i+1]*(i+1);
	}
	for(int i=vmax-1;i>=1;i--){
		invs[i]=finv[i]*fact[i-1];
	}
}
mint choose(int n,int k){
	return fact[n]*finv[n-k]*finv[k];
}
mint binom(int a,int b){
	return fact[a+b]*finv[a]*finv[b];
}
mint catalan(int n){
	return binom(n,n)-(n-1>=0?binom(n-1,n+1):0);
}

void dfs(int v,vi&vis,int&vn,int&ec,int&nc,const vvc<int>&g,const vi&need){
	assert(vis[v]==0);
	vis[v]=1;
	vn++;
	nc^=need[v];
	for(auto to:g[v]){
		if(vis[to]==0){
			dfs(to,vis,vn,ec,nc,g,need);
		}else if(vis[to]==1){
			ec++;
		}
	}
	vis[v]=2;
}

mint slv(int n,vc<tuple<ll,ll,ll>> es){
	if(n%2==0)return mint(2).pow(n*(n-1)/2-es.size());
	vi need(n);
	vvc<int> g(n,vi(n,1));
	for(auto e:es){
		ll a,b,c;tie(a,b,c)=e;
		need[a]^=c;
		need[b]^=c;
		g[a][b]=0;
		g[b][a]=0;
	}
	vvc<int> h(n);
	rep(i,n)rep(j,n)if(i!=j)if(g[i][j])
		h[i].pb(j);
	vi vis(n);
	mint ans=1;
	rep(i,n)if(vis[i]==0){
		int vn=0,ec=0,nc=0;
		dfs(i,vis,vn,ec,nc,h,need);
		if(nc)imp();
		ans*=mint(2).pow(ec-vn+1);
	}
	return ans;
}

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);
	
	int n;cin>>n;n--;
	vc<string> s(n);
	rep(i,n)cin>>s[i];
	
	rep(i,n)rng(j,i+1,n)if(s[i][j]!='?'){
		if(s[j][i]!='?'&&s[j][i]!=s[i][j]){
			imp();
		}
		s[j][i]=s[i][j];
	}
	
	rep(i,n)rng(j,n-i,n)if(s[i][j]!='?'){
		if(s[n-1-j][n-1-i]!='?'&&s[n-1-j][n-1-i]!=s[i][j]){
			imp();
		}
		s[n-1-j][n-1-i]=s[i][j];
	}
	
	int z=n+2;
	
	vi tp(z);
	rep(i,z)
		if(i<z-1&&i%2==0)tp[i]=1;
	
	vi vs[2];
	rep(i,z)
		vs[tp[i]].pb(i);
	
	vc<tuple<int,int,int>> es[2];
	
	rep(i,n)rep(j,min(i,n-1-i)+1)if(s[i][j]!='?'){
		int x=i+j+1;
		int y=i-j-1;
		if(y==-1)y=n+1;
		assert(tp[x]==tp[y]);
		int t=tp[x];
		x=lower_bound(all(vs[t]),x)-vs[t].bg;
		y=lower_bound(all(vs[t]),y)-vs[t].bg;
		int w=s[i][j]=='o';
		es[t].eb(x,y,w);
	}
	
	mint ans=1;
	
	rep(k,2)
		ans*=slv(vs[k].size(),es[k]);
	cout<<ans<<endl;
}

```