#pragma GCC optimize ("Ofast")
#include<bits/stdc++.h>
using namespace std;
#define MD (1000000007U)
struct Modint{
unsigned val;
Modint(){
val=0;
}
Modint(int a){
val = ord(a);
}
Modint(unsigned a){
val = ord(a);
}
Modint(long long a){
val = ord(a);
}
Modint(unsigned long long a){
val = ord(a);
}
inline unsigned ord(unsigned a){
return a%MD;
}
inline unsigned ord(int a){
a %= (int)MD;
if(a < 0){
a += MD;
}
return a;
}
inline unsigned ord(unsigned long long a){
return a%MD;
}
inline unsigned ord(long long a){
a %= (int)MD;
if(a < 0){
a += MD;
}
return a;
}
inline unsigned get(){
return val;
}
inline Modint &operator+=(Modint a){
val += a.val;
if(val >= MD){
val -= MD;
}
return *this;
}
inline Modint &operator-=(Modint a){
if(val < a.val){
val = val + MD - a.val;
}
else{
val -= a.val;
}
return *this;
}
inline Modint &operator*=(Modint a){
val = ((unsigned long long)val*a.val)%MD;
return *this;
}
inline Modint &operator/=(Modint a){
return *this *= a.inverse();
}
inline Modint operator+(Modint a){
return Modint(*this)+=a;
}
inline Modint operator-(Modint a){
return Modint(*this)-=a;
}
inline Modint operator*(Modint a){
return Modint(*this)*=a;
}
inline Modint operator/(Modint a){
return Modint(*this)/=a;
}
inline Modint operator+(int a){
return Modint(*this)+=Modint(a);
}
inline Modint operator-(int a){
return Modint(*this)-=Modint(a);
}
inline Modint operator*(int a){
return Modint(*this)*=Modint(a);
}
inline Modint operator/(int a){
return Modint(*this)/=Modint(a);
}
inline Modint operator+(long long a){
return Modint(*this)+=Modint(a);
}
inline Modint operator-(long long a){
return Modint(*this)-=Modint(a);
}
inline Modint operator*(long long a){
return Modint(*this)*=Modint(a);
}
inline Modint operator/(long long a){
return Modint(*this)/=Modint(a);
}
inline Modint operator-(void){
Modint res;
if(val){
res.val=MD-val;
}
else{
res.val=0;
}
return res;
}
inline operator bool(void){
return val!=0;
}
inline operator int(void){
return get();
}
inline operator long long(void){
return get();
}
inline Modint inverse(){
int a = val;
int b = MD;
int u = 1;
int v = 0;
int t;
Modint res;
while(b){
t = a / b;
a -= t * b;
swap(a, b);
u -= t * v;
swap(u, v);
}
if(u < 0){
u += MD;
}
res.val = u;
return res;
}
inline Modint pw(unsigned long long b){
Modint a(*this);
Modint res;
res.val = 1;
while(b){
if(b&1){
res *= a;
}
b >>= 1;
a *= a;
}
return res;
}
inline bool operator==(int a){
return ord(a)==val;
}
inline bool operator!=(int a){
return ord(a)!=val;
}
}
;
inline Modint operator+(int a, Modint b){
return Modint(a)+=b;
}
inline Modint operator-(int a, Modint b){
return Modint(a)-=b;
}
inline Modint operator*(int a, Modint b){
return Modint(a)*=b;
}
inline Modint operator/(int a, Modint b){
return Modint(a)/=b;
}
inline Modint operator+(long long a, Modint b){
return Modint(a)+=b;
}
inline Modint operator-(long long a, Modint b){
return Modint(a)-=b;
}
inline Modint operator*(long long a, Modint b){
return Modint(a)*=b;
}
inline Modint operator/(long long a, Modint b){
return Modint(a)/=b;
}
template<class S, class T> inline S chmax(S &a, T b){
if(a<b){
a=b;
}
return a;
}
#define main dummy_main
int main(){
return 0;
}
#undef main
int X;
int Y;
int mx[100][100];
Modint cnt[100][100];
void ren(int &mx, Modint &cnt, int a, Modint b){
if(mx < a){
mx = a;
cnt = 0;
}
if(mx == a){
cnt += b;
}
}
class Solution{
public:
vector<int> pathsWithMaxScore(vector<string>& S){
int i;
X = S.size();
Y = S[0].size();
S[0][0] = '0';
mx[X-1][Y-1] = 0;
cnt[X-1][Y-1] = 1;
for(i=(X)-1;i>=(0);i--){
int j;
for(j=(Y)-1;j>=(0);j--){
if(S[i][j]=='S'){
continue;
}
if(S[i][j]=='X'){
mx[i][j] = -1073709056;
cnt[i][j] = 0;
continue;
}
mx[i][j] = -1073709056;
cnt[i][j] = 0;
if(i+1 < X){
ren(mx[i][j], cnt[i][j], mx[i+1][j]+S[i][j]-'0', cnt[i+1][j]);
}
if(j+1 < Y){
ren(mx[i][j], cnt[i][j], mx[i][j+1]+S[i][j]-'0', cnt[i][j+1]);
}
if(i+1 < X && j+1 < Y){
ren(mx[i][j], cnt[i][j], mx[i+1][j+1]+S[i][j]-'0', cnt[i+1][j+1]);
}
}
}
chmax(mx[0][0], 0);
return vector<int>{mx[0][0], (int)cnt[0][0]};
}
}
;
// cLay varsion 20200217-1
// --- original code ---
// #define main dummy_main
// {}
// #undef main
//
// int X, Y, mx[100][100];
// Modint cnt[100][100];
//
// void ren(int &mx, Modint &cnt, int a, Modint b){
// if(mx < a) mx = a, cnt = 0;
// if(mx == a) cnt += b;
// }
//
// class Solution {
// public:
// vector<int> pathsWithMaxScore(vector<string>& S) {
// X = S.size();
// Y = S[0].size();
// S[0][0] = '0';
//
// mx[X-1][Y-1] = 0;
// cnt[X-1][Y-1] = 1;
// rrep(i,X) rrep(j,Y){
// if(S[i][j]=='S') continue;
// if(S[i][j]=='X') mx[i][j] = -int_inf, cnt[i][j] = 0, continue;
// mx[i][j] = -int_inf;
// cnt[i][j] = 0;
//
// if(i+1 < X) ren(mx[i][j], cnt[i][j], mx[i+1][j]+S[i][j]-'0', cnt[i+1][j]);
// if(j+1 < Y) ren(mx[i][j], cnt[i][j], mx[i][j+1]+S[i][j]-'0', cnt[i][j+1]);
// if(i+1 < X && j+1 < Y) ren(mx[i][j], cnt[i][j], mx[i+1][j+1]+S[i][j]-'0', cnt[i+1][j+1]);
// }
//
// mx[0][0] >?= 0;
// return vector<int>{mx[0][0], (int)cnt[0][0]};
// }
// };