#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;

const ll MOD = 998244353;

long long modpow(long long x, long long n){
    long long  res = 1;
    long long mul = x;
    while(n){
        if(n % 2) res = res * mul % MOD;
        mul = mul * mul % MOD;
        n /= 2;
    }
    return res;
}

struct Combination
{
    int maxn;
    std::vector<long long> fact;
    std::vector<long long> ifact;
    
    Combination(int maxn) : maxn(maxn){
        fact.resize(maxn + 1);
        ifact.resize(maxn + 1);
        fact[0] = 1;
        for(int i = 1; i <= maxn; i++) fact[i] = fact[i - 1] * i % MOD;
        ifact[maxn] = modpow(fact[maxn], MOD - 2);
        for(int i = maxn - 1; i >= 0; i--) ifact[i] = ifact[i + 1] * (i + 1) % MOD;
    }

    long long com(int n, int k){
        if(k > n || k < 0) return 0;
        if(k == n || k == 0) return 1;
        return (fact[n] * ifact[k] % MOD) * ifact[n - k] % MOD;
    }
};

struct PrimeDecomposition
{
    int n;
    vector<bool> p;
    vector<int> prime;
    vector<int> d;
    
    PrimeDecomposition(int n) : n(n){
        p.resize(n + 1);
        d.resize(n + 1);
        d[1] = 1;
        for(int i = 2; i <= n; i++){
            if(!p[i]){
                prime.push_back(i);
                for(int j = i; j <= n; j += i){
                    if(!p[j]) d[j] = i;
                    p[j] = true;
                }
            }
        }
    }
    
    vector<int> decomposition(int x){
        vector<int> res;
        while(x > 1){
            res.push_back(d[x]);
            x /= d[x];
        }
        return res;
    }
};

int main()
{
    int n, m;
    cin >> n >> m;
    PrimeDecomposition dec(m);
    Combination com(n * 2 + m);
    ll ans = 1;
    for(int i = 2; i <= m; i++){
        vector<int> v = dec.decomposition(i);
        int l = v.size();
        ll s = 1;
        int c = 1;
        for(int i = 1; i <= l; i++){
            if(i == l || v[i] != v[i - 1]){
                s = s * com.com(n + c - 1, c) % MOD;
                c = 1;
            }
            else c++;
            if(i == l) break;
        }
        ans = (ans + s) % MOD;
    }
    cout << ans << endl;
}

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

#define rep(i, a, b) for(int i = (a); i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define endl '\n'

typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef vector<ll> vll;

const ll mod = 1000000007;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

int main() {
    ios::sync_with_stdio(false); 
    cin.tie(0); 

    int r, c;
    cin >> r >> c;

    vector<string> g(r);
    vector<vector<pair<int,int>>> occ(26);

    pair<int,int> start;
    pair<int,int> goal;

    for(int i = 0; i < r; i++) {
    	cin >> g[i];
    	for(int j = 0; j < c; j++) {
    		if(g[i][j] == 'S') {
    			start = mp(i, j);
    		} else if(g[i][j] == 'G') {
    			goal = mp(i, j);
    		} else if(isalpha(g[i][j])) {
    			occ[g[i][j] - 'a'].pb(mp(i, j));
    		}
    	}
    }

    queue<pair<int,int>> q;
    vector<vector<bool>> vis(r, vector<bool>(c));
    vector<bool> visColor(26);
    q.push(start);
    vector<vector<int>> dist(r, vector<int>(c, 1 << 30));
    dist[start.first][start.second] = 0;

    int dx[4] = {-1,1,0,0};
    int dy[4] = {0,0,1,-1};

    while(!q.empty()) {
    	pii p = q.front();
    	q.pop();

    	int i = p.first;
    	int j = p.second;

    	if(isalpha(g[i][j]) && g[i][j] != 'S' && g[i][j] != 'G' && !visColor[g[i][j] - 'a']) {
    		trav(e, occ[g[i][j] - 'a']) {
    			int nr = e.first;
    			int nc = e.second;
    			if(!vis[nr][nc] && g[nr][nc] != '#') {
    				dist[nr][nc] = 1 + dist[i][j];
    				vis[nr][nc] = true;
    				q.push(mp(nr, nc));
    			}
    		}
    		visColor[g[i][j] - 'a'] = true;
    	}
    		

    	for(int x = 0; x < 4; x++) {
    		int nr = i + dx[x];
    		int nc = j + dy[x];
    		if(nr >= 0 && nr < r && nc < c && nc >= 0) {
    			if(!vis[nr][nc] && g[nr][nc] != '#') {
    				dist[nr][nc] = 1 + dist[i][j];
    				q.push(mp(nr, nc));
    				vis[nr][nc] = true;
    			}
    		}
    	}
    }

    cout << (dist[goal.first][goal.second] == 1 << 30 ? -1 : dist[goal.first][goal.second]) << endl;

    return 0;
}

