Problem:
Score : 1100 points

Problem Statement

There are N white balls arranged in a row, numbered 1,2,..,N from left to right.
AtCoDeer the deer is thinking of painting some of these balls red and blue, while leaving some of them white.

You are given a string s of length K.
AtCoDeer performs the following operation for each i from 1 through K in order:

The i-th operation: Choose a contiguous segment of balls (possibly empty), and paint these balls red if the i-th character in s is r; paint them blue if the character is b.

Here, if a ball which is already painted is again painted, the color of the ball will be overwritten.
However, due to the properties of dyes, it is not possible to paint a white, unpainted ball directly in blue.
That is, when the i-th character in s is b, the chosen segment must not contain a white ball.

After all the operations, how many different sequences of colors of the balls are possible?
Since the count can be large, find it modulo 10^9+7.

Constraints

1 ≤ N ≤ 70

1 ≤ K ≤ 70

|s| = K

s consists of r and b.

N and K are integers.

Input

Input is given from Standard Input in the following format:

N K
s

Output

Print the number of the different possible sequences of colors of the balls after all the operations, modulo 10^9+7.

Sample Input 1

2 2
rb

Sample Output 1

9

There are nine possible sequences of colors of the balls, as follows:

ww, wr, rw, rr, wb, bw, bb, rb, br.

Here, r represents red, b represents blue and wrepresents white.

Sample Input 2

5 2
br

Sample Output 2

16

Since we cannot directly paint white balls in blue, we can only choose an empty segment in the first operation.

Sample Input 3

7 4
rbrb

Sample Output 3

1569

Sample Input 4

70 70
bbrbrrbbrrbbbbrbbrbrrbbrrbbrbrrbrbrbbbbrbbrbrrbbrrbbbbrbbrbrrbbrrbbbbr

Sample Output 4

841634130

Solution in Rust (1.15.1) (judge verdict: Time Limit Exceeded)

use std::io::*;
use std::str::FromStr;
use std::collections::HashMap;

#[allow(dead_code)]
fn read<T: FromStr>() -> T {
    let stdin = stdin();
    let stdin = stdin.lock();
    let token: String = stdin
        .bytes()
        .map(|c| c.expect("failed to read char") as char)
        .skip_while(|c| c.is_whitespace())
        .take_while(|c| !c.is_whitespace())
        .collect();
    token.parse().ok().expect("failed to parse token")
}

#[allow(dead_code)]
fn pow_mod(base: i64, power: i64, modulo: i64) -> i64 {
    let mut base = base;
    let mut power = power;
    let mut ans = 1;
    while power > 0 {
        if power & 1 == 1 { ans = ans * base % modulo; }
        power >>= 1;
        base = base * base % modulo;
    }
    ans
}

#[allow(dead_code)]
fn inv_mod(a: i64, modulo: i64) -> i64 {
    pow_mod(a, modulo - 2, modulo)
}

const MOD: i64 = 1e+9 as i64 + 7;
const FACT_MAX: usize = 100000;
static mut FACTORIAL: [i64; FACT_MAX + 1] = [0; FACT_MAX + 1];
static mut RFACTORIAL: [i64; FACT_MAX + 1] = [0; FACT_MAX + 1];
fn init_fact() {
    unsafe {
        if FACTORIAL[0] == 0 {
            FACTORIAL[0] = 1;
            for i in 1..FACT_MAX+1 {
                FACTORIAL[i] = (FACTORIAL[i - 1] * i as i64) % MOD;
            }
            RFACTORIAL[FACT_MAX] = inv_mod(FACTORIAL[FACT_MAX], MOD);
            for i in (0..FACT_MAX).rev() {
                RFACTORIAL[i] = RFACTORIAL[i + 1] * (i as i64 + 1) % MOD;
            }
        }
    }
}
#[allow(dead_code)]
fn fact(n: usize) -> i64 {
    init_fact();
    unsafe {
        FACTORIAL[n]
    }
}
#[allow(dead_code, unused_comparisons)]
fn combi(n: usize, m: usize) -> i64 {
    if n < m || m < 0 { return 0; }
    init_fact();
    unsafe {
        FACTORIAL[n] * RFACTORIAL[m] % MOD * RFACTORIAL[n - m] % MOD
    }
}

fn get_min_size(g: usize) -> usize {
    if g <= 2 { 1 } else { (g - 2) * 2 + 1 }
}
fn total_size(groups: &Vec<usize>) -> usize {
    groups.iter().fold(0, |sum, v| sum + get_min_size(*v) + 1) - 1
}
fn is_valid(groups: &Vec<usize>, n: usize, s: &Vec<char>) -> bool {
    // println!("{:?}", groups);
    if groups.len() == 0 { return true; }
    let k = s.len();
    let sum = total_size(groups);
    // println!("{:?} {}", groups, sum);
    if sum > n { return false; }
    let mut used = vec![false; k];
    let mut rindex = vec![k; groups.len()];
    'rloop: for (i, _) in groups.iter().rev().enumerate() {
        for j in 0..k {
            if used[j] || s[j] == 'b' { continue; }
            used[j] = true;
            rindex[i] = j;
            continue 'rloop;
        }
        return false;
    }
    'bloop: for (i, g) in groups.iter().rev().enumerate() {
        if *g == 1 { continue; }
        for j in rindex[i]+1..k {
            if used[j] || s[j] == 'r' { continue; }
            used[j] = true;
            rindex[i] = j;
            continue 'bloop;
        }
        return false;
    }
    'lastloop: for (i, g) in groups.iter().rev().enumerate() {
        if *g <= 2 { continue; }
        let mut rest = g - 2;
        for j in rindex[i] + 1..k {
            if used[j] { continue; }
            used[j] = true;
            rest -= 1;
            if rest == 0 { continue 'lastloop; }
        }
        return false;
    }
    true
}

struct Solver {
    memo: Vec<HashMap<Vec<usize>, i32>>,
    memo_rb_seq: [[i32; 100]; 100],
}
impl Solver {
fn new() -> Solver {
    Solver {
        memo: vec![HashMap::new(); 100],
        memo_rb_seq: [[-1; 100]; 100],
    }
}

fn calc_rb_seq(&mut self, g: usize, w: usize) -> i64 {
    if w == 0 { return 0; }
    if g == 1 { return 1; }
    if self.memo_rb_seq[g][w] != -1 { return self.memo_rb_seq[g][w] as i64; }
    // println!("{} {}", g, w);
    let mut ret = 0;
    for i in 0..3 {
        let use_width = get_min_size(g) + i;
        let amp = [1, 2, 1][i];
        if w < use_width { continue; }
        ret = (ret + amp * combi(w - 1, use_width - 1)) % MOD;
        // println!("cnt {} {}", use_width, ret);
    }
    self.memo_rb_seq[g][w] = ret as i32;
    ret
}
fn calc_inner(&mut self, groups: &Vec<usize>, sum: usize, n: usize, index: usize, rest: usize) -> i64 {
    if index == groups.len() { return 1; }
    if sum > rest { return 0; }
    if let Some(ret) = self.memo[rest].get(&groups[index..]) {
        // println!("{:?} {}", groups[index..].to_vec(), ret);
        return *ret as i64;
    }
    if groups[index] == 1 {
        let ones = groups.len() - index;
        return combi(rest, 2 * ones);
    }
    let g = get_min_size(groups[index]);
    let mut ret = 0;
    ret = (ret + self.calc_inner(groups, sum, n, index, rest - 1)) % MOD;
    for i in g..rest {
        let mut nrest = rest - i - 1;
        // println!("{} {} {}", index, rest, nrest);
        let cnt = self.calc_rb_seq(groups[index], i);
        ret = (ret + cnt * self.calc_inner(groups, sum - (g + 1), n, index + 1, nrest)) % MOD;
    }
    self.memo[rest].insert(groups[index..].to_vec(), ret as i32);
    ret
}

fn calc(&mut self, groups: &Vec<usize>, n: usize) -> i64 {
    let groups = groups.iter().cloned().rev().collect::<Vec<usize>>();
    let mut cnts = HashMap::<usize, usize>::new();
    for g in groups.iter() {
        let cnt = cnts.entry(*g).or_insert(0);
        *cnt += 1;
    }
    let mut amp = 1;
    let mut rest = groups.len();
    for cnt in cnts.values() {
        amp = (amp * combi(rest, *cnt)) % MOD;
        rest -= *cnt;
    }
    // println!("{} {:?}", n, groups);
    let sum = total_size(&groups) + 1;
    let ret = amp * self.calc_inner(&groups, sum, n, 0, n + 1) % MOD;
    // println!("{} {:?} {}", n, groups, ret);
    ret
}

fn solve(&mut self, groups: &mut Vec<usize>, depth: usize, n: usize, s: &Vec<char>) -> i64 {
    if depth > n + 1 { return 0; }
    let mut ans = 0;
    groups.push(depth);
    if is_valid(groups, n, s) {
        ans = (ans + self.calc(groups, n)) % MOD;
        ans = (ans + self.solve(groups, depth, n, s)) % MOD;
    }
    groups.pop();
    ans = (ans + self.solve(groups, depth + 1, n, s)) % MOD;
    return ans;
}
}

fn main() {
    let n: usize = read();
    let _: usize = read();
    let s: String = read();
    let s = s.chars().collect::<Vec<char>>();
    let mut solver = Solver::new();
    let ans = (1 + solver.solve(&mut vec![], 1, n, &s)) % MOD;
    println!("{}", ans);
}