#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#define deb(x) cout << #x << " " << x << endl;
#define mod 1000000007
#define fast std::ios::sync_with_stdio(false), cin.tie(NULL), cout.tie(NULL);
#define endl "\n"

const ll INF = 1e18;
const ll NEGINF = -1 * INF;

/*NOTES: Take care of ll vs int
         Never use an iterator after erasing it
*/

const int N = 2e5 + 5;
vector<array<ll, 2>> adjList[N];
ll dist[N];

void dfs(int currNode, int parent, ll currDist)
{
    dist[currNode] = currDist;
    for (array<ll, 2> v : adjList[currNode])
    {
        if (v[0] != parent)
        {
            dfs(v[0], currNode, currDist ^ v[1]);
        }
    }
}

ll my_pow(ll a, ll n, ll m = INF)
{
    ll res = 1;
    while (n)
    {
        if (n % 2)
        {
            res = (res * a) % m;
            n--;
        }
        a = (a * a) % m;
        n /= 2;
    }
    return res;
}

void solve()
{
    int n;
    cin >> n;
    ll u, v, w;
    for (int i = 0; i < n - 1; i++)
    {
        cin >> u >> v >> w;
        u--;
        v--;
        adjList[u].push_back({v, w});
        adjList[v].push_back({u, w});
    }
    dfs(0, -1, 0ll);
    ll ans = 0;
    for (ll i = 0; i < 60; i++)
    {
        ll cntOnes = 0;
        ll cntZeros = 0;
        for (int j = 0; j < n; j++)
        {
            if (dist[j] & (1ll << i))
            {
                cntOnes++;
            }
            else
            {
                cntZeros++;
            }
        }
        ll totCnt = (cntOnes * cntZeros) % mod;
        ans = (ans + ((1ll << i) % mod * totCnt) % mod);
    }
    ans = ans % mod;
    //ans = (ans % mod * my_pow(2, mod - 2, mod) % mod) % mod;
    cout << ans << endl;
}

int main()
{
    fast;
#ifndef ONLINE_JUDGE
    freopen("/home/kalit/Desktop/Data Structures-Algo-Competitive/src/codeforces/input.txt", "r", stdin);
    freopen("/home/kalit/Desktop/Data Structures-Algo-Competitive/src/codeforces/output.txt", "w", stdout);
#endif
    int T = 1;
    while (T--)
    {
        solve();
    }
    //cout<< "Done in " << clock() / CLOCKS_PER_SEC <<"sec"<< endl;
    return 0;
}
// I SELL YOU...! 
#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
#include<queue>
#include<chrono>
#include<iomanip>
#include<map>
#include<set>
using namespace std;
using ll = long long;
using P = pair<ll,ll>;
using TP = tuple<ll,ll,ll>;
void init_io(){
  cin.tie(0);
  ios::sync_with_stdio(false);
  cout << fixed << setprecision(18);
}
const ll MOD = 998244353;
const ll MAX = 5100;
bool can[MAX][MAX][3];
ll dp[MAX][MAX]={};
ll modinv(ll a, ll m){
  ll b=m,u=1,v=0;
  while(b){
    ll t=a/b;
    a-=t*b; swap(a,b);
    u-=t*v; swap(u,v);
  }
  u%=m;
  if(u<0) u+=m;
  return u;
}
signed main(){
  init_io();
  ll H,W,K,fi=1,mv;
  cin >> H >> W >> K;
  mv = modinv(3,MOD);
  vector<ll> h(K),w(K);
  vector<char> c(K);
  for(int i=0;i<MAX;i++){
    for(int j=0;j<MAX;j++){
      for(int k=0;k<3;k++){
        can[i][j][k] = true;
      }
    }
  }
  for(ll i=0;i<H*W-K;i++){
    fi *= 3;
    fi %= MOD;
  }
  for(int i=0;i<K;i++){
    cin >> h[i] >> w[i] >> c[i];
    h[i]--;
    w[i]--;
    for(int j=0;j<3;j++){
      can[h[i]][w[i]][j] = false;
    }
    if(c[i]=='R') can[h[i]][w[i]][0] = true;
    if(c[i]=='D') can[h[i]][w[i]][1] = true;
    if(c[i]=='X') can[h[i]][w[i]][2] = true;
  }
  dp[0][0] = 1;
  for(int i=0;i<H;i++){
    for(int j=0;j<W;j++){
      ll nv = dp[i][j];
      if(can[i][j][0]&&can[i][j][1]&&can[i][j][2]){
        nv = (nv*2*mv);
        nv %= MOD;
        dp[i][j+1] = (dp[i][j+1]+nv)%MOD;
        dp[i+1][j] = (dp[i+1][j]+nv)%MOD;
      }else if(can[i][j][0]){
        dp[i][j+1] = (dp[i][j+1]+nv)%MOD;
      }else if(can[i][j][1]){
        dp[i+1][j] = (dp[i+1][j]+nv)%MOD;
      }else if(can[i][j][2]){
        dp[i][j+1] = (dp[i][j+1]+nv)%MOD;
        dp[i+1][j] = (dp[i+1][j]+nv)%MOD;
      }
    }
  }
  cout << (dp[H-1][W-1]*fi)%MOD << endl;
}
