use std::cmp::min;

const MOD: usize = 998244353;

fn main() {
    let (r, w) = (std::io::stdin(), std::io::stdout());
    let mut sc = IO::new(r.lock(), w.lock());
    let n: usize = sc.read();
    let s = sc.chars();

    let mut balls = vec![vec![]; 3];
    for i in 0..(3 * n) {
        match s[i] {
            'B' => {
                balls[0].push(i);
            }
            'R' => {
                balls[1].push(i);
            }
            'G' => {
                balls[2].push(i);
            }
            _ => unreachable!(),
        }
    }

    let mut is_right = vec![false; 3 * n];
    let mut is_left = vec![false; 3 * n];
    let mut is_center = vec![false; 3 * n];
    for i in 0..n {
        let mut b = vec![balls[0][i], balls[1][i], balls[2][i]];
        b.sort();
        is_left[b[0]] = true;
        is_center[b[1]] = true;
        is_right[b[2]] = true;
    }

    let mut left_count = vec![0; n];
    let mut cur = 0;
    let mut stack = 0;
    for i in 0..(3 * n) {
        if is_left[i] {
            stack += 1;
        }
        if is_center[i] {
            left_count[cur] = stack;
            stack -= 1;
            cur += 1;
        }
    }

    let mut right_count = vec![0; n];
    let mut cur = n;
    let mut stack = 0;
    for i in (0..(3 * n)).rev() {
        if is_right[i] {
            stack += 1;
        }
        if is_center[i] {
            right_count[cur - 1] = stack;
            cur -= 1;
            stack -= 1;
        }
    }

    let mut ans = 1;
    for i in 0..n {
        ans *= left_count[i];
        ans %= MOD;
        ans *= right_count[i];
        ans %= MOD;
    }

    for i in 0..n {
        ans *= i + 1;
        ans %= MOD;
    }

    println!("{}", ans);
}

pub mod fenwick_tree {
    /// `FenwickTree` is a data structure that can efficiently update elements
    /// and calculate prefix sums in a table of numbers.
    /// [https://en.wikipedia.org/wiki/Fenwick_tree](https://en.wikipedia.org/wiki/Fenwick_tree)
    pub struct FenwickTree<T> {
        n: usize,
        data: Vec<T>,
        init: T,
    }

    impl<T: Copy + ::std::ops::AddAssign + ::std::ops::Sub<Output = T>> FenwickTree<T> {
        /// Constructs a new `FenwickTree`. The size of `FenwickTree` should be specified by `size`.
        pub fn new(size: usize, init: T) -> FenwickTree<T> {
            FenwickTree {
                n: size + 1,
                data: vec![init; size + 1],
                init: init,
            }
        }

        pub fn add(&mut self, k: usize, value: T) {
            let mut x = k;
            while x < self.n {
                self.data[x] += value;
                x |= x + 1;
            }
        }

        /// Returns a sum of range `[l, r)`
        pub fn sum(&self, l: usize, r: usize) -> T {
            self.sum_one(r) - self.sum_one(l)
        }

        /// Returns a sum of range `[0, k)`
        pub fn sum_one(&self, k: usize) -> T {
            assert!(k < self.n, "k={} n={}", k, self.n);

            let mut result = self.init;
            let mut x = k as i32 - 1;
            while x >= 0 {
                result += self.data[x as usize];
                x = (x & (x + 1)) - 1;
            }

            result
        }
    }
}

pub struct IO<R, W: std::io::Write>(R, std::io::BufWriter<W>);

impl<R: std::io::Read, W: std::io::Write> IO<R, W> {
    pub fn new(r: R, w: W) -> Self {
        IO(r, std::io::BufWriter::new(w))
    }
    pub fn write<S: ToString>(&mut self, s: S) {
        use std::io::Write;
        self.1.write(s.to_string().as_bytes()).unwrap();
    }
    pub fn read<T: std::str::FromStr>(&mut self) -> T {
        use std::io::Read;
        let buf = self
            .0
            .by_ref()
            .bytes()
            .map(|b| b.unwrap())
            .skip_while(|&b| b == b' ' || b == b'\n' || b == b'\r' || b == b'\t')
            .take_while(|&b| b != b' ' && b != b'\n' && b != b'\r' && b != b'\t')
            .collect::<Vec<_>>();
        unsafe { std::str::from_utf8_unchecked(&buf) }
            .parse()
            .ok()
            .expect("Parse error.")
    }
    pub fn vec<T: std::str::FromStr>(&mut self, n: usize) -> Vec<T> {
        (0..n).map(|_| self.read()).collect()
    }
    pub fn chars(&mut self) -> Vec<char> {
        self.read::<String>().chars().collect()
    }
}


Measured memory_bytes: 14248