/*input
2 3
..#
#..

*/
#include<bits/stdc++.h>
//#include <ext/pb_ds/assoc_container.hpp>
//#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
//using namespace __gnu_pbds;
//typedef tree<pair<int,int>, null_type, less<pair<int,int>>, rb_tree_tag, tree_order_statistics_node_update> indexed_set;
#pragma GCC optimize("unroll-loops,no-stack-protector")
//order_of_key #of elements less than x
// find_by_order kth element
typedef long long int ll;
#define ld double
#define pii pair<int,int>
#define f first
#define s second
#define pb push_back
#define REP(i,n) for(ll i=0;i<n;i++)
#define REP1(i,n) for(int i=1;i<=n;i++)
#define FILL(n,x) memset(n,x,sizeof(n))
#define ALL(_a) _a.begin(),_a.end()
#define sz(x) (int)x.size()
const ll maxn=2e3+5;
const ll maxlg=__lg(maxn)+2;
const ll INF64=4e18;
const int INF=0x3f3f3f3f;
const ll MOD=1e9+7;
const ld PI=3.14159265358979323846;
const ld eps=1e-9;
#define lowb(x) x&(-x)
#define MNTO(x,y) x=min(x,(__typeof__(x))y)
#define MXTO(x,y) x=max(x,(__typeof__(x))y)
#define SORT_UNIQUE(c) (sort(c.begin(),c.end()), c.resize(distance(c.begin(),unique(c.begin(),c.end()))))
#define GET_POS(c,x) (lower_bound(c.begin(),c.end(),x)-c.begin())
#define MP make_pair
ll mult(ll a,ll b){
    return ((a%MOD)*(b%MOD))%MOD;
}
ll mypow(ll a,ll b){
    ll res=1LL;
    while(b){
        if(b&1) res=mult(res,a);
        a=mult(a,a);
        b>>=1;
    }
    return res;
}
string arr[maxn];
vector<int> r[maxn],c[maxn];
int main(){
    ios::sync_with_stdio(false),cin.tie(0);
    int n,m;
    cin>>n>>m;
    REP(i,n) cin>>arr[i];
    REP(i,n){
        r[i].pb(-1);
        REP(j,m){
            if(arr[i][j]=='#') r[i].pb(j);
        }
        r[i].pb(m);
    }
    int k=n*m;
    REP(j,m){
        c[j].pb(-1);
        REP(i,n){
            if(arr[i][j]=='#') c[j].pb(i),--k;
        }
        c[j].pb(n);
    }
    ll ans=0;
    REP(i,n){
        REP(j,m){
            if(arr[i][j]=='#') continue;
            ll d=(*upper_bound(ALL(r[i]),j)-*prev(upper_bound(ALL(r[i]),j)))-1;
            ll d2=(*upper_bound(ALL(c[j]),i)-*prev(upper_bound(ALL(c[j]),i)))-1;
            //cout<<i<<' '<<j<<' '<<d<<' '<<d2<<'\n';
            ans+=mult(mypow(2,d+d2-1)-1,mypow(2,k-(d+d2-1)));
            ans%=MOD;
        }
    }
    cout<<ans;
}
//region
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pi;
typedef pair<ll, ll> pl;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<string> vs;
#define fastio ios_base::sync_with_stdio(0);cin.tie(NULL);
#define endl "\n"
#define pb push_back
#define all(X) begin((X)), end((X))
#define sz(X) (int)(X).size()
#define fi first
#define se second
#define fv(X) for(auto&_:(X))cin>>_
#define fv2(X) for(auto&__:(X))fv(__)
#define lbound(X, n) (lower_bound(all(X), n) - begin(X))
#define ubound(X, n) (upper_bound(all(X), n) - begin(X))
#ifdef LOCAL
template<size_t S>
string to_string(const bitset<S> &x) { return x.to_string(); }
string to_string(const string &x) { return '"' + x + '"'; }
string to_string(char x) { return string{'\'', x, '\''}; }
string to_string(bool x) { return x ? "true" : "false"; }
template<typename Head, typename Tail>
string to_string(const pair<Head, Tail> &x) { return "(" + to_string(x.first) + ", " + to_string(x.second) + ")"; }
template<class T>
string to_string(T x) {
    string ret = "[";
    for (const auto &i: x)
        ret += to_string(i) + ", ";
    if (sz(ret) > 1)
        ret = ret.substr(0, sz(ret) - 2);
    return ret += "]";
}
string to_string(const char *x) { return string(x); }
string to_string() { return ""; }
template<typename Head, typename... Tail>
string to_string(Head H, Tail... T) { return to_string(H) + ", " + to_string(T...); }
#define debug(...) cerr << "[" << #__VA_ARGS__ << "]: " << to_string(__VA_ARGS__) << endl
#else
#define debug(...) 42
#endif
//endregion

void solve() {
    int n;
    cin >> n;
    n *= 2;
    vl R, G, B;
    for (int i = 0; i < n; i++) {
        ll a;
        string c;
        cin >> a >> c;
        if (c == "R")
            R.pb(a);
        else if (c == "G")
            G.pb(a);
        else
            B.pb(a);
    }
    vl even, odd1, odd2;
    if (sz(R) % 2 == 0 && sz(G) % 2 == 0 && sz(B) % 2 == 0) {
        cout << 0;
        return;
    }
    if (sz(R) % 2 == 0) {
        even = R;
        odd1 = G;
        odd2 = B;
    } else if (sz(G) % 2 == 0) {
        even = G;
        odd1 = R;
        odd2 = B;
    } else {
        even = B;
        odd1 = R;
        odd2 = G;
    }
    sort(all(even));
    sort(all(odd1));
    sort(all(odd2));

    auto get_diff_min = [&](vl a1, vl a2, int exclude_idx = -1) {
       int i = 0, j = 0;
       ll ret = 4e18;
       int i1, i2;
       while (i < sz(a1) && j < sz(a2)) {
           if (i == exclude_idx) {
               i++;
               continue;
           }
           if (ret > abs(a1[i] - a2[j])) {
               ret = abs(a1[i] - a2[j]);
               i1 = i;
               i2 = j;
           }
           if (a1[i] < a2[j])
               i++;
           else
               j++;
       }
       return vl{ret, i1, i2};
    };

    auto eo1_diff = get_diff_min(even, odd1);
    auto eo2_diff = get_diff_min(even, odd2);
    auto o1o2_diff = get_diff_min(odd1, odd2);

    if (sz(even) == 0) {
        cout << o1o2_diff[0];
        return;
    }
    if (eo1_diff[1] != eo2_diff[2]) {
        cout << min(o1o2_diff[0], eo1_diff[0] + eo2_diff[0]);
        return;
    }

    int exclude_idx = eo1_diff[1];
    auto eo1_exclude_diff = get_diff_min(even, odd1, exclude_idx);
    auto eo2_exclude_diff = get_diff_min(even, odd2, exclude_idx);

    cout << min(o1o2_diff[0],
                min(eo1_exclude_diff[0] + eo2_diff[0], eo1_diff[0] + eo2_exclude_diff[0])
    );
}

int main() {
    fastio
    solve();
    return 0;
}