Problem:
Problem K
Black and White Boxes
Alice and Bob play the following game.
There are a number of straight piles of boxes. The boxes have the same size and are painted either black or white.
Two players, namely Alice and Bob, take their turns alternately. Who to play first is decided by a fair random draw.
In Alice's turn, she selects a black box in one of the piles, and removes the box together with all the boxes above it, if any. If no black box to remove is left, she loses the game.
In Bob's turn, he selects a white box in one of the piles, and removes the box together with all the boxes above it, if any. If no white box to remove is left, he loses the game.
Given an initial configuration of piles and who plays first, the game is a
definite perfect information game
. In such a game, one of the players has sure win provided he or she plays best. The draw for the first player, thus, essentially decides the winner.
In fact, this seemingly boring property is common with many popular games, such as chess. The chess game, however, is complicated enough to prevent thorough analyses, even by supercomputers, which leaves us rooms to enjoy playing.
This game of box piles, however, is not as complicated. The best plays may be more easily found. Thus, initial configurations should be fair, that is, giving both players chances to win. A configuration in which one player can always win, regardless of who plays first, is undesirable.
You are asked to arrange an initial configuration for this game by picking a number of piles from the given candidate set. As more complicated configuration makes the game more enjoyable, you are expected to find the configuration with the maximum number of boxes among fair ones.
Input
The input consists of a single test case, formatted as follows.
$n$
$p_1$
.
.
.
$p_n$
A positive integer $n$ ($\leq 40$) is the number of candidate piles. Each $p_i$ is a string of characters
B
and
W
, representing the $i$-th candidate pile.
B
and
W
mean black and white boxes, respectively. They appear in the order in the pile, from bottom to top. The number of boxes in a candidate pile does not exceed 40.
Output
Output in a line the maximum possible number of boxes in a fair initial configuration consisting of some of the candidate piles. If only the empty configuration is fair, output a zero.
Sample Input 1
4
B
W
WB
WB
Sample Output 1
5
Sample Input 2
6
B
W
WB
WB
BWW
BWW
Sample Output 2
10

Submitted solutions:

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

#define mem(t, v)   memset ((t) , v, sizeof(t))
#define all(x)      x.begin(),x.end()
#define un(x)       x.erase(unique(all(x)), x.end())
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define sl(n)       scanf("%lld", &n)
#define sll(a,b)    scanf("%lld %lld", &a, &b)
#define slll(a,b,c) scanf("%lld %lld %lld", &a, &b, &c)
#define D(x)        cerr << __LINE__ << ": " << #x << " = " << (x) << '\n'
#define DD(x,y)     cerr << __LINE__ << ": " << #x << " = " << x << "   " << #y << " = " << y << '\n'
#define DDD(x,y,z)  cerr << __LINE__ << ": " << #x << " = " << x << "   " << #y << " = " << y << "   " << #z << " = " << z << '\n'
#define DBG         cerr << __LINE__ << ": Hi" << '\n'
#define pb          push_back
#define PI          acos(-1.00)
#define xx          first
#define yy          second
#define eps         1e-9

typedef unsigned long long int ULL;
typedef long long int LL;
typedef pair<int,int> pii;
typedef pair<LL,LL> pll;


inline int setBit(int N, int pos) { return N=N | (1<<pos); }
inline int resetBit(int N, int pos) { return N= N & ~(1<<pos); }
inline bool checkBit(int N, int pos) { return (bool)(N & (1<<pos)); }

//int fx[] = {+0, +0, +1, -1, -1, +1, -1, +1};
//int fy[] = {-1, +1, +0, +0, +1, +1, -1, -1}; //Four & Eight Direction

int n;
pll B[50];
char s[50];
const LL V = 1LL<<40;
pll process()
{
    pll box;
    box.yy = strlen(s);
    if(s[0] == 'W')
        box.xx = V;
    else
        box.xx = -V;
    LL tmp = box.xx;
    int st = -1;
    for(int i = 1; i<box.yy; i++)
    {
        if(s[i] == s[0])
            box.xx += tmp;
        else
        {
            st = i;
            break;
        }
    }
    if(st == -1)
        return box;
    LL nw = 2;
    for(int i = st; i<box.yy; i++)
    {
        if(s[i] == 'W')
            box.xx += (V/nw);
        else
            box.xx -= (V/nw);
        nw <<= 1;
    }
    return box;
}

int ans = 0;
map<LL,int>M;
void call(int pos, LL sum, int b)
{
    if(pos > n/2)
    {
        if(sum == 0)
            ans = max(ans, b);
        if(M.find(sum) != M.end())
            M[sum] = max(M[sum], b);
        else
            M[sum] = b;
        return;
    }

    call(pos+1, sum, b);
    call(pos+1, B[pos].xx+sum, b + B[pos].yy);
}

void solve(int pos, LL sum, int b)
{
    if(pos > n)
    {
        LL need = -sum;
        if(M.find(need) != M.end())
            ans = max(ans, b+M[need]);
        return;
    }

    solve(pos+1, sum, b);
    solve(pos+1, B[pos].xx+sum, b + B[pos].yy);
}

int main()
{
    //freopen("maxon.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    sf(n);
    for(int i = 1; i<=n; i++)
    {
        scanf("%s",s);
        B[i] = process();
    }

    call(1,0,0);
    solve(n/2+1, 0, 0);
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 860
memory_kb: 69016
final_rank: 6

code_snippet: #ifdef NACHIA
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 1ll << 60;
#define REP(i,n) for(ll i=0; i<ll(n); i++)
template<class T>
using V = vector<T>;
template<class T>
using VV = V<V<T>>;
template<class A, class B>
bool chmax(A &a, B b){ return a < b && (a = b, true); }
template<class A, class B>
bool chmin(A &a, B b){ return b < a && (a = b, true); }

struct Surreal {
  using S = Surreal;
  using Int = long long;
  Int p, q; // val = p / 2**q
  Surreal(Int p = 0, Int q = 0) : p(p), q(q) {
    while (p % 2 == 0 && q) p /= 2, q--;
  }
  S operator+(S r) const {
    auto cq = max(q, r.q);
    auto cp = (p << (cq - q)) + (r.p << (cq - r.q));
    return S(cp, cq);
  }
  S operator-() const { return {-p, q}; }
  bool operator<(S r) const { return (r + -*this).p > 0; }
  S lchild() const {
    if (!q && p <= 0) return p - 1;
    return { p * 2 - 1, q + 1 };
  }
  friend S operator|(S l, S r) {
    assert(l < r);
    S v = 0;
    while (!(l < v && v < r))
      v = l < v ? v.lchild() : -(-v).lchild();
    return v;
  }
};

map<string, Surreal> dpmem;
V<string> game_move(string s){
  V<string> ans;
  REP(i,s.size()) if(s[i] == 'W'){
    ans.push_back(s.substr(0, i));
  }
  return ans;
}
string game_flip(string s){
  for(char& c : s) c = (c == 'B') ? 'W' : 'B';
  return s;
}
Surreal dp(string s){
  if(s.empty()) return 0;
  if(dpmem.count(s)) return dpmem[s];
  auto nx0 = game_move(s);
  auto nx1 = game_move(game_flip(s));
  Surreal f = -1000;
  for(auto x : nx0) f = max(f, dp(x));
  Surreal g = -1000;
  for(auto x : nx1) g = max(g, dp(x));
  return dpmem[s] = (f | -g);
}

void testcase(){
  int N; cin >> N;
  V<string> S(N); REP(i,N) cin >> S[i];
  V<Surreal> F0, F1;
  V<ll> sz0, sz1;
  REP(i,N){
    auto s = dp(S[i]);
    F0.push_back(s);
    sz0.push_back(S[i].size());
    swap(F0, F1);
    swap(sz0, sz1);
  }
  V<pair<Surreal, ll>> buf;
  REP(i,1<<F0.size()){
    ll cnt = 0;
    Surreal s = 0;
    REP(j,F0.size()) if(i&(1<<j)){ s = s + F0[j]; cnt += sz0[j]; }
    buf.push_back({ s, -cnt });
  }
  sort(buf.begin(), buf.end());
  ll ans = 0;
  REP(i,1<<F1.size()){
    ll cnt = 0;
    Surreal s = 0;
    REP(j,F1.size()) if(i&(1<<j)){ s = s + F1[j]; cnt += sz1[j]; }
    auto it = lower_bound(buf.begin(), buf.end(), make_pair(-s, -INF));
    if(it == buf.end() || (it->first + s).p) continue;
    chmax(ans, cnt - it->second);
  }

  cout << ans << "\n";
}

int main(){
  cin.tie(0)->sync_with_stdio(0);
  testcase();
  return 0;
}
accuracy: 1
time_ms: 370
memory_kb: 29536
final_rank: 1

code_snippet: #ifdef NACHIA
#define _GLIBCXX_DEBUG
#endif
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 1ll << 60;
#define REP(i,n) for(ll i=0; i<ll(n); i++)
template<class T>
using V = vector<T>;
template<class T>
using VV = V<V<T>>;
template<class A, class B>
bool chmax(A &a, B b){ return a < b && (a = b, true); }
template<class A, class B>
bool chmin(A &a, B b){ return b < a && (a = b, true); }

struct Surreal {
  using S = Surreal;
  using Int = long long;
  Int p, q; // val = p / 2**q
  Surreal(Int p = 0, Int q = 0) : p(p), q(q) {
    while (p % 2 == 0 && q) p /= 2, q--;
  }
  S operator+(S r) const {
    auto cq = max(q, r.q);
    auto cp = (p << (cq - q)) + (r.p << (cq - r.q));
    return S(cp, cq);
  }
  S operator-() const { return {-p, q}; }
  bool operator<(S r) const { return (r + -*this).p > 0; }
  S lchild() const {
    if (!q && p <= 0) return p - 1;
    return { p * 2 - 1, q + 1 };
  }
  friend S operator|(S l, S r) {
    assert(l < r);
    S v = 0;
    while (!(l < v && v < r))
      v = l < v ? v.lchild() : -(-v).lchild();
    return v;
  }
};

map<string, Surreal> dpmem;
V<string> game_move(string s){
  V<string> ans;
  REP(i,s.size()) if(s[i] == 'W'){
    ans.push_back(s.substr(0, i));
  }
  return ans;
}
string game_flip(string s){
  for(char& c : s) c = (c == 'B') ? 'W' : 'B';
  return s;
}
Surreal dp(string s){
  if(s.empty()) return 0;
  if(dpmem.count(s)) return dpmem[s];
  auto nx0 = game_move(s);
  auto nx1 = game_move(game_flip(s));
  Surreal f = -1000;
  for(auto x : nx0) f = max(f, dp(x));
  Surreal g = -1000;
  for(auto x : nx1) g = max(g, dp(x));
  return dpmem[s] = (f | -g);
}

void testcase(){
  int N; cin >> N;
  V<string> S(N); REP(i,N) cin >> S[i];
  V<Surreal> F0, F1;
  V<ll> sz0, sz1;
  REP(i,N){
    F0.push_back(dp(S[i]));
    sz0.push_back(S[i].size());
    swap(F0, F1);
    swap(sz0, sz1);
  }
  V<pair<Surreal, ll>> buf;
  REP(i,1<<F0.size()){
    ll cnt = 0;
    Surreal s = 0;
    REP(j,F0.size()) if(i&(1<<j)){ s = s + F0[j]; cnt += sz0[j]; }
    buf.push_back({ s, -cnt });
  }
  sort(buf.begin(), buf.end());
  ll ans = 0;
  REP(i,1<<F1.size()){
    ll cnt = 0;
    Surreal s = 0;
    REP(j,F0.size()) if(i&(1<<j)){ s = s + F1[j]; cnt += sz1[j]; }
    s = -s;
    auto it = lower_bound(buf.begin(), buf.end(), make_pair(s, -INF));
    if(it == buf.end() || (it->first + -s).p) continue;
    chmax(ans, cnt - it->second);
  }

  cout << ans << "\n";
}

int main(){
  cin.tie(0)->sync_with_stdio(0);
  testcase();
  return 0;
}
accuracy: 0.7272727272727273
time_ms: 280
memory_kb: 29460
final_rank: 14

code_snippet: // AOJ #1377
// Black and White Boxes 2025.2.1

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

const ll FIX = (1LL << 40);
 
ll computeGameValue(const string &S) {
    int L = S.size();
    vector<ll> dp(L+1, 0);
    dp[0] = 0;
    for (int i = 1; i <= L; i++){
        bool hasLeft = false, hasRight = false;
        ll leftMax = -LLONG_MAX;
        ll rightMin = LLONG_MAX;
        for (int j = 0; j < i; j++){
            if(S[j]=='B'){
                hasLeft = true;
                leftMax = max(leftMax, dp[j]);
            } else if(S[j]=='W'){
                hasRight = true;
                rightMin = min(rightMin, dp[j]);
            }
        }
        ll val;
        if(!hasLeft && hasRight) val = rightMin - FIX;
        else if(hasLeft && !hasRight) val = leftMax + FIX;
        else if(hasLeft && hasRight) val = (leftMax + rightMin) / 2;
        else val = 0;
        dp[i] = val;
    }
    return dp[L];
}
 
struct Item { ll val; int weight; };
struct PairData { ll sumVal; int totWeight; };
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
 
    int n;
    cin >> n;
    vector<Item> items;
    items.reserve(n);
    for (int i=0; i<n; i++){
        string pile;
        cin >> pile;
        ll gv = computeGameValue(pile);
        int w = pile.size();
        items.push_back({gv, w});
    }
 
    int n1 = n/2;
    int n2 = n - n1;
    vector<Item> group1(items.begin(), items.begin()+n1);
    vector<Item> group2(items.begin()+n1, items.end());
 
    unordered_map<ll,int> best1, best2;
 
    int total1 = 1 << n1;
    for (int mask = 0; mask < total1; mask++){
        ll sumVal = 0;
        int totWeight = 0;
        for (int j = 0; j < n1; j++){
            if(mask & (1 << j)){
                sumVal += group1[j].val;
                totWeight += group1[j].weight;
            }
        }
        if(best1.find(sumVal)==best1.end()){
            best1[sumVal] = totWeight;
        } else {
            best1[sumVal] = max(best1[sumVal], totWeight);
        }
    }
 
    int total2 = 1 << n2;
    for (int mask = 0; mask < total2; mask++){
        ll sumVal = 0;
        int totWeight = 0;
        for (int j = 0; j < n2; j++){
            if(mask & (1 << j)){
                sumVal += group2[j].val;
                totWeight += group2[j].weight;
            }
        }
        if(best2.find(sumVal)==best2.end()){
            best2[sumVal] = totWeight;
        } else {
            best2[sumVal] = max(best2[sumVal], totWeight);
        }
    }
 
    int ans = 0;
    if(best1.find(0) != best1.end() && best1[0] > 0) ans = max(ans, best1[0]);
    if(best2.find(0) != best2.end() && best2[0] > 0) ans = max(ans, best2[0]);
 
    for(auto &p: best1){
        ll s = p.first;
        int w1 = p.second;
        ll need = -s;
        if(best2.find(need) != best2.end()){
            int w2 = best2[need];
            if(w1 + w2 > 0)
                ans = max(ans, w1 + w2);
        }
    }
 
    cout << ans << endl;
    return 0;
}
accuracy: 1
time_ms: 570
memory_kb: 99740
final_rank: 9

code_snippet: /**
 * date   : 2023-05-25 15:58:02
 * author : Nyaan
 */

#define NDEBUG

using namespace std;

// intrinstic
#include <immintrin.h>

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cfenv>
#include <cfloat>
#include <chrono>
#include <cinttypes>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <initializer_list>
#include <iomanip>
#include <ios>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <streambuf>
#include <string>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

// utility

namespace Nyaan {
using ll = long long;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;

template <typename T>
using V = vector<T>;
template <typename T>
using VV = vector<vector<T>>;
using vi = vector<int>;
using vl = vector<long long>;
using vd = V<double>;
using vs = V<string>;
using vvi = vector<vector<int>>;
using vvl = vector<vector<long long>>;

template <typename T, typename U>
struct P : pair<T, U> {
  template <typename... Args>
  P(Args... args) : pair<T, U>(args...) {}

  using pair<T, U>::first;
  using pair<T, U>::second;

  P &operator+=(const P &r) {
    first += r.first;
    second += r.second;
    return *this;
  }
  P &operator-=(const P &r) {
    first -= r.first;
    second -= r.second;
    return *this;
  }
  P &operator*=(const P &r) {
    first *= r.first;
    second *= r.second;
    return *this;
  }
  template <typename S>
  P &operator*=(const S &r) {
    first *= r, second *= r;
    return *this;
  }
  P operator+(const P &r) const { return P(*this) += r; }
  P operator-(const P &r) const { return P(*this) -= r; }
  P operator*(const P &r) const { return P(*this) *= r; }
  template <typename S>
  P operator*(const S &r) const {
    return P(*this) *= r;
  }
  P operator-() const { return P{-first, -second}; }
};

using pl = P<ll, ll>;
using pi = P<int, int>;
using vp = V<pl>;

constexpr int inf = 1001001001;
constexpr long long infLL = 4004004004004004004LL;

template <typename T>
int sz(const T &t) {
  return t.size();
}

template <typename T, typename U>
inline bool amin(T &x, U y) {
  return (y < x) ? (x = y, true) : false;
}
template <typename T, typename U>
inline bool amax(T &x, U y) {
  return (x < y) ? (x = y, true) : false;
}

template <typename T>
inline T Max(const vector<T> &v) {
  return *max_element(begin(v), end(v));
}
template <typename T>
inline T Min(const vector<T> &v) {
  return *min_element(begin(v), end(v));
}
template <typename T>
inline long long Sum(const vector<T> &v) {
  return accumulate(begin(v), end(v), 0LL);
}

template <typename T>
int lb(const vector<T> &v, const T &a) {
  return lower_bound(begin(v), end(v), a) - begin(v);
}
template <typename T>
int ub(const vector<T> &v, const T &a) {
  return upper_bound(begin(v), end(v), a) - begin(v);
}

constexpr long long TEN(int n) {
  long long ret = 1, x = 10;
  for (; n; x *= x, n >>= 1) ret *= (n & 1 ? x : 1);
  return ret;
}

template <typename T, typename U>
pair<T, U> mkp(const T &t, const U &u) {
  return make_pair(t, u);
}

template <typename T>
vector<T> mkrui(const vector<T> &v, bool rev = false) {
  vector<T> ret(v.size() + 1);
  if (rev) {
    for (int i = int(v.size()) - 1; i >= 0; i--) ret[i] = v[i] + ret[i + 1];
  } else {
    for (int i = 0; i < int(v.size()); i++) ret[i + 1] = ret[i] + v[i];
  }
  return ret;
};

template <typename T>
vector<T> mkuni(const vector<T> &v) {
  vector<T> ret(v);
  sort(ret.begin(), ret.end());
  ret.erase(unique(ret.begin(), ret.end()), ret.end());
  return ret;
}

template <typename F>
vector<int> mkord(int N,F f) {
  vector<int> ord(N);
  iota(begin(ord), end(ord), 0);
  sort(begin(ord), end(ord), f);
  return ord;
}

template <typename T>
vector<int> mkinv(vector<T> &v) {
  int max_val = *max_element(begin(v), end(v));
  vector<int> inv(max_val + 1, -1);
  for (int i = 0; i < (int)v.size(); i++) inv[v[i]] = i;
  return inv;
}

vector<int> mkiota(int n) {
  vector<int> ret(n);
  iota(begin(ret), end(ret), 0);
  return ret;
}

template <typename T>
T mkrev(const T &v) {
  T w{v};
  reverse(begin(w), end(w));
  return w;
}

template <typename T>
bool nxp(vector<T> &v) {
  return next_permutation(begin(v), end(v));
}

template <typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;

}  // namespace Nyaan


// bit operation

namespace Nyaan {
__attribute__((target("popcnt"))) inline int popcnt(const u64 &a) {
  return _mm_popcnt_u64(a);
}
inline int lsb(const u64 &a) { return a ? __builtin_ctzll(a) : 64; }
inline int ctz(const u64 &a) { return a ? __builtin_ctzll(a) : 64; }
inline int msb(const u64 &a) { return a ? 63 - __builtin_clzll(a) : -1; }
template <typename T>
inline int gbit(const T &a, int i) {
  return (a >> i) & 1;
}
template <typename T>
inline void sbit(T &a, int i, bool b) {
  if (gbit(a, i) != b) a ^= T(1) << i;
}
constexpr long long PW(int n) { return 1LL << n; }
constexpr long long MSK(int n) { return (1LL << n) - 1; }
}  // namespace Nyaan


// inout

namespace Nyaan {

template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << p.first << " " << p.second;
  return os;
}
template <typename T, typename U>
istream &operator>>(istream &is, pair<T, U> &p) {
  is >> p.first >> p.second;
  return is;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  int s = (int)v.size();
  for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i];
  return os;
}
template <typename T>
istream &operator>>(istream &is, vector<T> &v) {
  for (auto &x : v) is >> x;
  return is;
}

istream &operator>>(istream &is, __int128_t &x) {
  string S;
  is >> S;
  x = 0;
  int flag = 0;
  for (auto &c : S) {
    if (c == '-') {
      flag = true;
      continue;
    }
    x *= 10;
    x += c - '0';
  }
  if (flag) x = -x;
  return is;
}

istream &operator>>(istream &is, __uint128_t &x) {
  string S;
  is >> S;
  x = 0;
  for (auto &c : S) {
    x *= 10;
    x += c - '0';
  }
  return is;
}

ostream &operator<<(ostream &os, __int128_t x) {
  if (x == 0) return os << 0;
  if (x < 0) os << '-', x = -x;
  string S;
  while (x) S.push_back('0' + x % 10), x /= 10;
  reverse(begin(S), end(S));
  return os << S;
}
ostream &operator<<(ostream &os, __uint128_t x) {
  if (x == 0) return os << 0;
  string S;
  while (x) S.push_back('0' + x % 10), x /= 10;
  reverse(begin(S), end(S));
  return os << S;
}

void in() {}
template <typename T, class... U>
void in(T &t, U &...u) {
  cin >> t;
  in(u...);
}

void out() { cout << "\n"; }
template <typename T, class... U, char sep = ' '>
void out(const T &t, const U &...u) {
  cout << t;
  if (sizeof...(u)) cout << sep;
  out(u...);
}

struct IoSetupNya {
  IoSetupNya() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    cerr << fixed << setprecision(7);
  }
} iosetupnya;

}  // namespace Nyaan


// debug


#ifdef NyaanDebug
#define trc(...) (void(0))
#else
#define trc(...) (void(0))
#endif

#ifdef NyaanLocal
#define trc2(...) (void(0))
#else
#define trc2(...) (void(0))
#endif


// macro

#define each(x, v) for (auto&& x : v)
#define each2(x, y, v) for (auto&& [x, y] : v)
#define all(v) (v).begin(), (v).end()
#define rep(i, N) for (long long i = 0; i < (long long)(N); i++)
#define repr(i, N) for (long long i = (long long)(N)-1; i >= 0; i--)
#define rep1(i, N) for (long long i = 1; i <= (long long)(N); i++)
#define repr1(i, N) for (long long i = (N); (long long)(i) > 0; i--)
#define reg(i, a, b) for (long long i = (a); i < (b); i++)
#define regr(i, a, b) for (long long i = (b)-1; i >= (a); i--)
#define fi first
#define se second
#define ini(...)   \
  int __VA_ARGS__; \
  in(__VA_ARGS__)
#define inl(...)         \
  long long __VA_ARGS__; \
  in(__VA_ARGS__)
#define ins(...)      \
  string __VA_ARGS__; \
  in(__VA_ARGS__)
#define in2(s, t)                           \
  for (int i = 0; i < (int)s.size(); i++) { \
    in(s[i], t[i]);                         \
  }
#define in3(s, t, u)                        \
  for (int i = 0; i < (int)s.size(); i++) { \
    in(s[i], t[i], u[i]);                   \
  }
#define in4(s, t, u, v)                     \
  for (int i = 0; i < (int)s.size(); i++) { \
    in(s[i], t[i], u[i], v[i]);             \
  }
#define die(...)             \
  do {                       \
    Nyaan::out(__VA_ARGS__); \
    return;                  \
  } while (0)


namespace Nyaan {
void solve();
}
int main() { Nyaan::solve(); }


//



using namespace std;




using namespace std;

// reference : http://www.ivis.co.jp/text/20111102.pdf
struct SurrealNumber {
  using S = SurrealNumber;
  using i64 = long long;

  // p / 2^q の形で保持
  i64 p, q;
  SurrealNumber(i64 _p = 0, i64 _q = 0) : p(_p), q(_q) {}
  friend ostream& operator<<(ostream& os, const SurrealNumber& r) {
    os << r.p;
    if (r.q != 0) os << " / " << (i64{1} << r.q);
    return os;
  }

  static S normalize(S s) {
    if (s.p != 0) {
      while (s.p % 2 == 0 and s.q != 0) s.p /= 2, s.q--;
    } else {
      s.q = 0;
    }
    return {s.p, s.q};
  }

  // 加算・減算
  friend S operator+(const S& l, const S& r) {
    i64 cq = max(l.q, r.q);
    i64 cp = (l.p << (cq - l.q)) + (r.p << (cq - r.q));
    return normalize(S{cp, cq});
  }
  friend S operator-(const S& l, const S& r) {
    i64 cq = max(l.q, r.q);
    i64 cp = (l.p << (cq - l.q)) - (r.p << (cq - r.q));
    return normalize(S{cp, cq});
  }
  S& operator+=(const S& r) { return (*this) = (*this) + r; }
  S& operator-=(const S& r) { return (*this) = (*this) - r; }

  S operator-() const { return {-p, q}; }
  S operator+() const { return {p, q}; }

  // 大小関係
  friend bool operator<(const S& l, const S& r) { return (r - l).p > 0; }
  friend bool operator<=(const S& l, const S& r) { return (r - l).p >= 0; }
  friend bool operator>(const S& l, const S& r) { return (l - r).p > 0; }
  friend bool operator>=(const S& l, const S& r) { return (l - r).p >= 0; }
  friend bool operator==(const S& l, const S& r) { return (l - r).p == 0; }
  friend bool operator!=(const S& l, const S& r) { return (l - r).p != 0; }

  // 左右の子を返す関数
  pair<S, S> child() const {
    if (p == 0) return {-1, 1};
    if (q == 0 and p > 0) return {S{p * 2 - 1, 1}, p + 1};
    if (q == 0 and p < 0) return {p - 1, S{p * 2 + 1, 1}};
    return {(*this) - S{1, q + 1}, (*this) + S{1, q + 1}};
  }

  S larger() const {
    S root = 0;
    while ((*this) >= root) root = root.child().second;
    return root;
  }
  S smaller() const {
    S root = 0;
    while ((*this) <= root) root = root.child().first;
    return root;
  }
  friend S reduce(const S& l, const S& r) {
    assert(l < r);
    S root = 0;
    while (l >= root or root >= r) {
      auto [lr, rr] = root.child();
      root = (r <= root ? lr : rr);
    }
    return root;
  }
};

/**
 * @brief 超現実数
 */


// F : pair(vector<Game>, vector<Game>) を返す関数
template <typename Game, typename F>
struct PartisanGameSolver {
  using Games = vector<Game>;
  using S = SurrealNumber;

  map<Game, S> mp;
  F f;

  PartisanGameSolver(const F& _f) : f(_f) {}

  S zero() const { return S{0}; }

  S get(Game g) {
    if (mp.count(g)) return mp[g];
    return mp[g] = _get(g);
  }

 private:
  S _get(Game g) {
    Games gl, gr;
    tie(gl, gr) = f(g);
    if (gl.empty() and gr.empty()) return 0;
    vector<S> l, r;
    for (auto& cg : gl) l.push_back(get(cg));
    for (auto& cg : gr) r.push_back(get(cg));
    S sl, sr;
    if (!l.empty()) sl = *max_element(begin(l), end(l));
    if (!r.empty()) sr = *min_element(begin(r), end(r));
    if (r.empty()) return sl.larger();
    if (l.empty()) return sr.smaller();
    assert(sl < sr);
    return reduce(sl, sr);
  }
};

/**
 * @brief 非不偏ゲーム
 */


//



using namespace std;




using namespace std;




using namespace std;

namespace internal {
unsigned long long non_deterministic_seed() {
  unsigned long long m =
      chrono::duration_cast<chrono::nanoseconds>(
          chrono::high_resolution_clock::now().time_since_epoch())
          .count();
  m ^= 9845834732710364265uLL;
  m ^= m << 24, m ^= m >> 31, m ^= m << 35;
  return m;
}
unsigned long long deterministic_seed() { return 88172645463325252UL; }

// 64 bit の seed 値を生成 (手元では seed 固定)
// 連続で呼び出すと同じ値が何度も返ってくるので注意
unsigned long long seed() {
#if defined(NyaanLocal) && !defined(NON_DETERMINISTIC_SEED)
  return deterministic_seed();
#else
  return non_deterministic_seed();
#endif
}

}  // namespace internal



using namespace std;

namespace internal {
template <typename T>
using is_broadly_integral =
    typename conditional_t<is_integral_v<T> || is_same_v<T, __int128_t> ||
                               is_same_v<T, __uint128_t>,
                           true_type, false_type>::type;

template <typename T>
using is_broadly_signed =
    typename conditional_t<is_signed_v<T> || is_same_v<T, __int128_t>,
                           true_type, false_type>::type;

template <typename T>
using is_broadly_unsigned =
    typename conditional_t<is_unsigned_v<T> || is_same_v<T, __uint128_t>,
                           true_type, false_type>::type;

#define ENABLE_VALUE(x) \
  template <typename T> \
  constexpr bool x##_v = x<T>::value;

ENABLE_VALUE(is_broadly_integral);
ENABLE_VALUE(is_broadly_signed);
ENABLE_VALUE(is_broadly_unsigned);
#undef ENABLE_VALUE

#define ENABLE_HAS_TYPE(var)                                              \
  template <class, class = void>                                         \
  struct has_##var : std::false_type {};                                 \
  template <class T>                                                     \
  struct has_##var<T, std::void_t<typename T::var>> : std::true_type {}; \
  template <class T>                                                     \
  constexpr auto has_##var##_v = has_##var<T>::value;

}  // namespace internal


namespace internal {
// 整数, 整数列を 64 bit unsigned int へ移す

using u64 = unsigned long long;
using u128 = __uint128_t;

ENABLE_HAS_TYPE(first_type);
ENABLE_HAS_TYPE(second_type);
ENABLE_HAS_TYPE(iterator);

template <typename T>
u64 hash_function(const T& x) {
  static u64 r = seed();
  constexpr u64 z1 = 11995408973635179863ULL;
  if constexpr (is_broadly_integral_v<T>) {
    // Integral
    return (u64(x) ^ r) * z1;
  } else if constexpr (has_first_type_v<T> && has_second_type_v<T>) {
    // pair
    constexpr u64 z2 = 10150724397891781847ULL;
    return hash_function(x.first) + hash_function(x.second) * z2;
  } else if constexpr (has_iterator_v<T>) {
    // Container
    constexpr u64 mod = (1LL << 61) - 1;
    constexpr u64 base = 950699498548472943ULL;
    u64 m = 0;
    for (auto& z : x) {
      u64 w;
      if constexpr (is_broadly_integral_v<T>) {
        w = u64(z) ^ r;
      } else {
        w = hash_function(z);
      }
      u128 y = u128(m) * base + (w & mod);
      m = (y & mod) + (y >> 61);
      if (m >= mod) m -= mod;
    }
    m ^= m << 24, m ^= m >> 31, m ^= m << 35;
    return m;
  } else {
    static_assert([]() { return false; }());
  }
}

template <typename Key>
struct HashObject {
  size_t operator()(const Key& x) const { return hash_function(x); }
};

}  // namespace internal

/*
@brief ハッシュ関数
*/

// 削除不可能な hashmap
//
// テンプレート引数
// Key : Int, string, vector 辺りは何でも (小数系は無理)
// Val : 何でも
// init_size : 初期バケットサイズ
// fixed_size : これを true にするするとバケットサイズが固定になる
// 引数
// _default_value : Val の初期値, この値で初期化される
template <typename Key, typename Val, int init_size = 4,
          bool fixed_size = false>
struct UnerasableHashMap {
  static_assert(init_size >= 1 && (init_size & (init_size - 1)) == 0);

 private:
  int N, occupied_num;
  vector<Key> keys;
  vector<Val> vals;
  vector<char> flag;
  int shift;
  const Val default_value;

  // 64 bit の hash を返す
  static unsigned long long get_hash(const Key& x) {
    return internal::hash_function(x);
  }

  // サイズを n に拡張する
  void init(int n = init_size, bool reset = false) {
    vector<Key> keys2(n);
    vector<Val> vals2(n, default_value);
    vector<char> flag2(n);
    int shift2 = 64 - __builtin_ctz(n);
    swap(N, n), swap(keys, keys2);
    swap(vals, vals2), swap(flag, flag2), swap(shift, shift2);
    if (reset == false) {
      for (int i = 0; i < (int)flag2.size(); i++) {
        if (flag2[i]) {
          int j = hint(keys2[i]);
          keys[j] = keys2[i];
          vals[j] = vals2[i];
          flag[j] = 1;
        }
      }
    }
  }

  int hint(const Key& k) {
    int hash = get_hash(k) >> shift;
    while (flag[hash] && keys[hash] != k) hash = (hash + 1) & (N - 1);
    return hash;
  }

 public:
  UnerasableHashMap(const Val& _default_value = Val{})
      : occupied_num(0), default_value(_default_value) {
    init(init_size, true);
  }

  // key が i である要素への参照を返す
  Val& operator[](const Key& k) {
    int i = hint(k);
    if (!flag[i]) {
      if constexpr (fixed_size == false) {
        if (occupied_num * 2 >= N) {
          init(2 * N), i = hint(k);
        }
      }
      keys[i] = k, flag[i] = 1, occupied_num++;
    }
    return vals[i];
  }

  Val get(const Key& k) {
    int i = hint(k);
    return flag[i] ? vals[i] : default_value;
  }

  // 走査, f に関数 f(key, val) を入れる
  template <typename F>
  void enumerate(const F f) {
    for (int i = 0; i < (int)flag.size(); i++) {
      if (flag[i]) f(keys[i], vals[i]);
    }
  }

  int count(const Key& k) { return flag[hint(k)]; }
  bool contain(const Key& k) { return flag[hint(k)]; }
  int size() const { return occupied_num; }
  void reset() { init(init_size, true); }
  void clear() { init(init_size, true); }
};


using namespace Nyaan;

void q() {
  auto f = [&](const string& S) {
    V<string> a, b;
    rep(i, sz(S)) {
      string T = S.substr(0, i);
      (S[i] == 'B' ? a : b).push_back(T);
    }
    return make_pair(a, b);
  };
  PartisanGameSolver<string, decltype(f)> game(f);

  auto gen = [&](V<string> v) {
    int M = sz(v);
    V<SurrealNumber> w(M);
    rep(i, M) w[i] = game.get(v[i]);
    V<pair<SurrealNumber, int>> r(PW(M));
    rep1(b, PW(M) - 1) {
      int t = msb(b);
      r[b] = r[b - PW(t)];
      r[b].first += w[t];
      r[b].second += sz(v[t]);
    }
    return r;
  };

  ini(N);
  V<string> P(N);
  in(P);
  int M = N / 2;
  auto v = gen({begin(P), begin(P) + M});
  auto w = gen({begin(P) + M, end(P)});
  trc(v);
  trc(w);
  ll ans = 0;

  UnerasableHashMap<pl, int> mp;
  each(p, v) amax(mp[{p.first.p, p.first.q}], p.second);
  each(p, w) {
    pl key{-p.first.p, p.first.q};
    if (mp.count(key)) amax(ans, p.second + mp[key]);
  }
  out(ans);
}

void Nyaan::solve() {
  int t = 1;
  // in(t);
  while (t--) q();
}
accuracy: 1
time_ms: 90
memory_kb: 117924
final_rank: 8

code_snippet: /**
 * date   : 2023-05-25 15:53:42
 * author : Nyaan
 */

#define NDEBUG

using namespace std;

// intrinstic
#include <immintrin.h>

#include <algorithm>
#include <array>
#include <bitset>
#include <cassert>
#include <cctype>
#include <cfenv>
#include <cfloat>
#include <chrono>
#include <cinttypes>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdarg>
#include <cstddef>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <deque>
#include <fstream>
#include <functional>
#include <initializer_list>
#include <iomanip>
#include <ios>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <random>
#include <set>
#include <sstream>
#include <stack>
#include <streambuf>
#include <string>
#include <tuple>
#include <type_traits>
#include <typeinfo>
#include <unordered_map>
#include <unordered_set>
#include <utility>
#include <vector>

// utility

namespace Nyaan {
using ll = long long;
using i64 = long long;
using u64 = unsigned long long;
using i128 = __int128_t;
using u128 = __uint128_t;

template <typename T>
using V = vector<T>;
template <typename T>
using VV = vector<vector<T>>;
using vi = vector<int>;
using vl = vector<long long>;
using vd = V<double>;
using vs = V<string>;
using vvi = vector<vector<int>>;
using vvl = vector<vector<long long>>;

template <typename T, typename U>
struct P : pair<T, U> {
  template <typename... Args>
  P(Args... args) : pair<T, U>(args...) {}

  using pair<T, U>::first;
  using pair<T, U>::second;

  P &operator+=(const P &r) {
    first += r.first;
    second += r.second;
    return *this;
  }
  P &operator-=(const P &r) {
    first -= r.first;
    second -= r.second;
    return *this;
  }
  P &operator*=(const P &r) {
    first *= r.first;
    second *= r.second;
    return *this;
  }
  template <typename S>
  P &operator*=(const S &r) {
    first *= r, second *= r;
    return *this;
  }
  P operator+(const P &r) const { return P(*this) += r; }
  P operator-(const P &r) const { return P(*this) -= r; }
  P operator*(const P &r) const { return P(*this) *= r; }
  template <typename S>
  P operator*(const S &r) const {
    return P(*this) *= r;
  }
  P operator-() const { return P{-first, -second}; }
};

using pl = P<ll, ll>;
using pi = P<int, int>;
using vp = V<pl>;

constexpr int inf = 1001001001;
constexpr long long infLL = 4004004004004004004LL;

template <typename T>
int sz(const T &t) {
  return t.size();
}

template <typename T, typename U>
inline bool amin(T &x, U y) {
  return (y < x) ? (x = y, true) : false;
}
template <typename T, typename U>
inline bool amax(T &x, U y) {
  return (x < y) ? (x = y, true) : false;
}

template <typename T>
inline T Max(const vector<T> &v) {
  return *max_element(begin(v), end(v));
}
template <typename T>
inline T Min(const vector<T> &v) {
  return *min_element(begin(v), end(v));
}
template <typename T>
inline long long Sum(const vector<T> &v) {
  return accumulate(begin(v), end(v), 0LL);
}

template <typename T>
int lb(const vector<T> &v, const T &a) {
  return lower_bound(begin(v), end(v), a) - begin(v);
}
template <typename T>
int ub(const vector<T> &v, const T &a) {
  return upper_bound(begin(v), end(v), a) - begin(v);
}

constexpr long long TEN(int n) {
  long long ret = 1, x = 10;
  for (; n; x *= x, n >>= 1) ret *= (n & 1 ? x : 1);
  return ret;
}

template <typename T, typename U>
pair<T, U> mkp(const T &t, const U &u) {
  return make_pair(t, u);
}

template <typename T>
vector<T> mkrui(const vector<T> &v, bool rev = false) {
  vector<T> ret(v.size() + 1);
  if (rev) {
    for (int i = int(v.size()) - 1; i >= 0; i--) ret[i] = v[i] + ret[i + 1];
  } else {
    for (int i = 0; i < int(v.size()); i++) ret[i + 1] = ret[i] + v[i];
  }
  return ret;
};

template <typename T>
vector<T> mkuni(const vector<T> &v) {
  vector<T> ret(v);
  sort(ret.begin(), ret.end());
  ret.erase(unique(ret.begin(), ret.end()), ret.end());
  return ret;
}

template <typename F>
vector<int> mkord(int N,F f) {
  vector<int> ord(N);
  iota(begin(ord), end(ord), 0);
  sort(begin(ord), end(ord), f);
  return ord;
}

template <typename T>
vector<int> mkinv(vector<T> &v) {
  int max_val = *max_element(begin(v), end(v));
  vector<int> inv(max_val + 1, -1);
  for (int i = 0; i < (int)v.size(); i++) inv[v[i]] = i;
  return inv;
}

vector<int> mkiota(int n) {
  vector<int> ret(n);
  iota(begin(ret), end(ret), 0);
  return ret;
}

template <typename T>
T mkrev(const T &v) {
  T w{v};
  reverse(begin(w), end(w));
  return w;
}

template <typename T>
bool nxp(vector<T> &v) {
  return next_permutation(begin(v), end(v));
}

template <typename T>
using minpq = priority_queue<T, vector<T>, greater<T>>;

}  // namespace Nyaan


// bit operation

namespace Nyaan {
__attribute__((target("popcnt"))) inline int popcnt(const u64 &a) {
  return _mm_popcnt_u64(a);
}
inline int lsb(const u64 &a) { return a ? __builtin_ctzll(a) : 64; }
inline int ctz(const u64 &a) { return a ? __builtin_ctzll(a) : 64; }
inline int msb(const u64 &a) { return a ? 63 - __builtin_clzll(a) : -1; }
template <typename T>
inline int gbit(const T &a, int i) {
  return (a >> i) & 1;
}
template <typename T>
inline void sbit(T &a, int i, bool b) {
  if (gbit(a, i) != b) a ^= T(1) << i;
}
constexpr long long PW(int n) { return 1LL << n; }
constexpr long long MSK(int n) { return (1LL << n) - 1; }
}  // namespace Nyaan


// inout

namespace Nyaan {

template <typename T, typename U>
ostream &operator<<(ostream &os, const pair<T, U> &p) {
  os << p.first << " " << p.second;
  return os;
}
template <typename T, typename U>
istream &operator>>(istream &is, pair<T, U> &p) {
  is >> p.first >> p.second;
  return is;
}

template <typename T>
ostream &operator<<(ostream &os, const vector<T> &v) {
  int s = (int)v.size();
  for (int i = 0; i < s; i++) os << (i ? " " : "") << v[i];
  return os;
}
template <typename T>
istream &operator>>(istream &is, vector<T> &v) {
  for (auto &x : v) is >> x;
  return is;
}

istream &operator>>(istream &is, __int128_t &x) {
  string S;
  is >> S;
  x = 0;
  int flag = 0;
  for (auto &c : S) {
    if (c == '-') {
      flag = true;
      continue;
    }
    x *= 10;
    x += c - '0';
  }
  if (flag) x = -x;
  return is;
}

istream &operator>>(istream &is, __uint128_t &x) {
  string S;
  is >> S;
  x = 0;
  for (auto &c : S) {
    x *= 10;
    x += c - '0';
  }
  return is;
}

ostream &operator<<(ostream &os, __int128_t x) {
  if (x == 0) return os << 0;
  if (x < 0) os << '-', x = -x;
  string S;
  while (x) S.push_back('0' + x % 10), x /= 10;
  reverse(begin(S), end(S));
  return os << S;
}
ostream &operator<<(ostream &os, __uint128_t x) {
  if (x == 0) return os << 0;
  string S;
  while (x) S.push_back('0' + x % 10), x /= 10;
  reverse(begin(S), end(S));
  return os << S;
}

void in() {}
template <typename T, class... U>
void in(T &t, U &...u) {
  cin >> t;
  in(u...);
}

void out() { cout << "\n"; }
template <typename T, class... U, char sep = ' '>
void out(const T &t, const U &...u) {
  cout << t;
  if (sizeof...(u)) cout << sep;
  out(u...);
}

struct IoSetupNya {
  IoSetupNya() {
    cin.tie(nullptr);
    ios::sync_with_stdio(false);
    cout << fixed << setprecision(15);
    cerr << fixed << setprecision(7);
  }
} iosetupnya;

}  // namespace Nyaan


// debug


#ifdef NyaanDebug
#define trc(...) (void(0))
#else
#define trc(...) (void(0))
#endif

#ifdef NyaanLocal
#define trc2(...) (void(0))
#else
#define trc2(...) (void(0))
#endif


// macro

#define each(x, v) for (auto&& x : v)
#define each2(x, y, v) for (auto&& [x, y] : v)
#define all(v) (v).begin(), (v).end()
#define rep(i, N) for (long long i = 0; i < (long long)(N); i++)
#define repr(i, N) for (long long i = (long long)(N)-1; i >= 0; i--)
#define rep1(i, N) for (long long i = 1; i <= (long long)(N); i++)
#define repr1(i, N) for (long long i = (N); (long long)(i) > 0; i--)
#define reg(i, a, b) for (long long i = (a); i < (b); i++)
#define regr(i, a, b) for (long long i = (b)-1; i >= (a); i--)
#define fi first
#define se second
#define ini(...)   \
  int __VA_ARGS__; \
  in(__VA_ARGS__)
#define inl(...)         \
  long long __VA_ARGS__; \
  in(__VA_ARGS__)
#define ins(...)      \
  string __VA_ARGS__; \
  in(__VA_ARGS__)
#define in2(s, t)                           \
  for (int i = 0; i < (int)s.size(); i++) { \
    in(s[i], t[i]);                         \
  }
#define in3(s, t, u)                        \
  for (int i = 0; i < (int)s.size(); i++) { \
    in(s[i], t[i], u[i]);                   \
  }
#define in4(s, t, u, v)                     \
  for (int i = 0; i < (int)s.size(); i++) { \
    in(s[i], t[i], u[i], v[i]);             \
  }
#define die(...)             \
  do {                       \
    Nyaan::out(__VA_ARGS__); \
    return;                  \
  } while (0)


namespace Nyaan {
void solve();
}
int main() { Nyaan::solve(); }


//



using namespace std;




using namespace std;

// reference : http://www.ivis.co.jp/text/20111102.pdf
struct SurrealNumber {
  using S = SurrealNumber;
  using i64 = long long;

  // p / 2^q の形で保持
  i64 p, q;
  SurrealNumber(i64 _p = 0, i64 _q = 0) : p(_p), q(_q) {}
  friend ostream& operator<<(ostream& os, const SurrealNumber& r) {
    os << r.p;
    if (r.q != 0) os << " / " << (i64{1} << r.q);
    return os;
  }

  static S normalize(S s) {
    if (s.p != 0) {
      while (s.p % 2 == 0 and s.q != 0) s.p /= 2, s.q--;
    } else {
      s.q = 0;
    }
    return {s.p, s.q};
  }

  // 加算・減算
  friend S operator+(const S& l, const S& r) {
    i64 cq = max(l.q, r.q);
    i64 cp = (l.p << (cq - l.q)) + (r.p << (cq - r.q));
    return normalize(S{cp, cq});
  }
  friend S operator-(const S& l, const S& r) {
    i64 cq = max(l.q, r.q);
    i64 cp = (l.p << (cq - l.q)) - (r.p << (cq - r.q));
    return normalize(S{cp, cq});
  }
  S& operator+=(const S& r) { return (*this) = (*this) + r; }
  S& operator-=(const S& r) { return (*this) = (*this) - r; }

  S operator-() const { return {-p, q}; }
  S operator+() const { return {p, q}; }

  // 大小関係
  friend bool operator<(const S& l, const S& r) { return (r - l).p > 0; }
  friend bool operator<=(const S& l, const S& r) { return (r - l).p >= 0; }
  friend bool operator>(const S& l, const S& r) { return (l - r).p > 0; }
  friend bool operator>=(const S& l, const S& r) { return (l - r).p >= 0; }
  friend bool operator==(const S& l, const S& r) { return (l - r).p == 0; }
  friend bool operator!=(const S& l, const S& r) { return (l - r).p != 0; }

  // 左右の子を返す関数
  pair<S, S> child() const {
    if (p == 0) return {-1, 1};
    if (q == 0 and p > 0) return {S{p * 2 - 1, 1}, p + 1};
    if (q == 0 and p < 0) return {p - 1, S{p * 2 + 1, 1}};
    return {(*this) - S{1, q + 1}, (*this) + S{1, q + 1}};
  }

  S larger() const {
    S root = 0;
    while ((*this) >= root) root = root.child().second;
    return root;
  }
  S smaller() const {
    S root = 0;
    while ((*this) <= root) root = root.child().first;
    return root;
  }
  friend S reduce(const S& l, const S& r) {
    assert(l < r);
    S root = 0;
    while (l >= root or root >= r) {
      auto [lr, rr] = root.child();
      root = (r <= root ? lr : rr);
    }
    return root;
  }
};

/**
 * @brief 超現実数
 */


// F : pair(vector<Game>, vector<Game>) を返す関数
template <typename Game, typename F>
struct PartisanGameSolver {
  using Games = vector<Game>;
  using S = SurrealNumber;

  map<Game, S> mp;
  F f;

  PartisanGameSolver(const F& _f) : f(_f) {}

  S zero() const { return S{0}; }

  S get(Game g) {
    if (mp.count(g)) return mp[g];
    return mp[g] = _get(g);
  }

 private:
  S _get(Game g) {
    Games gl, gr;
    tie(gl, gr) = f(g);
    if (gl.empty() and gr.empty()) return 0;
    vector<S> l, r;
    for (auto& cg : gl) l.push_back(get(cg));
    for (auto& cg : gr) r.push_back(get(cg));
    S sl, sr;
    if (!l.empty()) sl = *max_element(begin(l), end(l));
    if (!r.empty()) sr = *min_element(begin(r), end(r));
    if (r.empty()) return sl.larger();
    if (l.empty()) return sr.smaller();
    assert(sl < sr);
    return reduce(sl, sr);
  }
};

/**
 * @brief 非不偏ゲーム
 */


using namespace Nyaan;

void q() {
  auto f = [&](const string& S) {
    V<string> a, b;
    rep(i, sz(S)) {
      string T = S.substr(0, i);
      (S[i] == 'B' ? a : b).push_back(T);
    }
    return make_pair(a, b);
  };
  PartisanGameSolver<string, decltype(f)> game(f);

  auto gen = [&](V<string> v) {
    int M = sz(v);
    V<SurrealNumber> w(M);
    rep(i, M) w[i] = game.get(v[i]);
    V<pair<SurrealNumber, int>> r(PW(M));
    rep(b, PW(M)) {
      rep(i, M) {
        if (gbit(b, i)) {
          r[b].first += w[i];
          r[b].second += sz(v[i]);
        }
      }
    }
    return r;
  };

  ini(N);
  V<string> P(N);
  in(P);
  int M = N / 2;
  auto v = gen({begin(P), begin(P) + M});
  auto w = gen({begin(P) + M, end(P)});
  trc(v);
  trc(w);
  ll ans = 0;
  map<SurrealNumber, int> mp;
  each(p, v) amax(mp[p.first], p.second);
  each(p, w) {
    if (mp.count(-p.first)) amax(ans, p.second + mp[-p.first]);
  }
  out(ans);
}

void Nyaan::solve() {
  int t = 1;
  // in(t);
  while (t--) q();
}
accuracy: 1
time_ms: 1100
memory_kb: 117932
final_rank: 11

code_snippet: #include <bits/stdc++.h>
using namespace std;
typedef __int128_t ll;
template<class T>bool chmax(T &a, const T &b) { if (a<b) { a=b; return true; } return false; }
template<class T>bool chmin(T &a, const T &b) { if (b<a) { a=b; return true; } return false; }
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second
#define mp make_pair
#define si(x) int(x.size())
const int mod=998244353,MAX=105;
const ll INF=1LL<<60;
using P=pair<ll,ll>;

//int128

//https://kopricky.github.io/code/Misc/int128.html

// __int128の入出力

using LL = __int128;
istream& operator>>(istream& is, LL& v)
{
    string s;
    is >> s;
    v = 0;
    for (int i = 0; i < (int)s.size(); i++) {
        if (isdigit(s[i])) { v = v * 10 + s[i] - '0'; }
    }
    if (s[0] == '-') { v *= -1; }
    return is;
}

ostream& operator<<(ostream& os, const LL& v)
{
    if (v == 0) { return (os << "0"); }
    LL num = v;
    if (v < 0) {
        os << '-';
        num = -num;
    }
    string s;
    for (; num > 0; num /= 10) { s.push_back((char)(num % 10) + '0'); }
    reverse(s.begin(), s.end());
    return (os << s);
}



P nor(P c){
    while(c.fi%2==0&&c.se%2==0){
        c.fi/=2;
        c.se/=2;
    }
    return c;
}

P add(P a,P b){
    while(a.se<b.se){
        a.fi*=2;
        a.se*=2;
    }
    while(a.se>b.se){
        b.fi*=2;
        b.se*=2;
    }
    P c=mp(a.fi+b.fi,a.se);
    return nor(c);
}

P ma(P a,P b){
    while(a.se<b.se){
        a.fi*=2;
        a.se*=2;
    }
    while(a.se>b.se){
        b.fi*=2;
        b.se*=2;
    }
    if(a.fi<=b.fi) return nor(b);
    else return nor(a);
}

P mi(P a,P b){
    while(a.se<b.se){
        a.fi*=2;
        a.se*=2;
    }
    while(a.se>b.se){
        b.fi*=2;
        b.se*=2;
    }
    if(a.fi<=b.fi) return nor(a);
    else return nor(b);
}

bool eq(P a,P b){
    while(a.se<b.se){
        a.fi*=2;
        a.se*=2;
    }
    while(a.se>b.se){
        b.fi*=2;
        b.se*=2;
    }
    if(a==b) return true;
    else return false;
}

P eval(P a,P b){
    if(a.fi<0&&b.fi>0) return mp(0,1);
    if(b.fi<=0){
        P x=mp(b.fi/b.se-1,1);
        //assert(ma(x,b)!=x);
        if(mi(x,a)!=x) return x;
    }
    if(a.fi>=0){
        P x=mp(a.fi/a.se+1,1);
        //assert(mi(x,a)!=x);
        if(ma(x,b)!=x) return x;
    }
    if(a.se==1&&b.se==1){
        return mp(a.fi+b.fi,2);
    }
    
    for(ll y=2;;y*=2){
        ll x=a.fi*y/a.se;
        if(ma(a,mp(x,y))==a) x++;
        if(mi(mp(x,y),b)!=b) return nor(mp(x,y));
        //assert(y<=(1LL<<36));
    }
    
    return mp(0,1);
}

map<string,P> MA;

P solve(string S){
    if(MA.count(S)) return MA[S];
    P a=mp(-INF,1),b=mp(INF,1);
    for(int i=0;i<si(S);i++){
        if(S[i]=='W'){
            a=ma(a,solve(S.substr(0,i)));
        }else{
            b=mi(b,solve(S.substr(0,i)));
        }
    }
    
    return MA[S]=eval(a,b);
}

int main() {
    
    std::ifstream in("text.txt");
    std::cin.rdbuf(in.rdbuf());
    cin.tie(0);
    ios::sync_with_stdio(false);
    
    int N;cin>>N;
    vector<string> S(N);
    for(int i=0;i<N;i++) cin>>S[i];
    vector<P> A(N);
    for(int i=0;i<N;i++){
        A[i]=solve(S[i]);
    }
    
    int ans=0;
    
    map<P,int> sv;
    int M=N/2;
    for(int bit=0;bit<(1<<M);bit++){
        P sum=mp(0,1);
        int len=0;
        for(int i=0;i<M;i++){
            if(bit&(1<<i)){
                sum=add(sum,A[i]);
                len+=si(S[i]);
            }
        }
        sum.fi*=(-1);
        chmax(sv[sum],len);
    }
    for(int bit=0;bit<(1<<(N-M));bit++){
        P sum=mp(0,1);
        int len=0;
        for(int i=0;i<N-M;i++){
            if(bit&(1<<i)){
                sum=add(sum,A[M+i]);
                len+=si(S[M+i]);
            }
        }
        if(sv.count(sum)){
            chmax(ans,sv[sum]+len);
        }
    }
    
    cout<<ans<<endl;
}
accuracy: 1
time_ms: 1120
memory_kb: 101796
final_rank: 10

code_snippet: #line 1 "e.cpp"
/**
 *	author: nok0
 *	created: 2022.04.06 15:16:23
**/
#line 1 "/Users/nok0/Documents/Programming/nok0/cftemp.hpp"
#include <bits/stdc++.h>
using namespace std;

#pragma region Macros
// rep macro
#define foa(v, a) for(auto &v : a)
#define REPname(a, b, c, d, e, ...) e
#define REP(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int i = 0; i < (x); ++i)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define REPSname(a, b, c, ...) c
#define REPS(...) REPSname(__VA_ARGS__, REPS1, REPS0)(__VA_ARGS__)
#define REPS0(x) for(int i = 1; i <= (x); ++i)
#define REPS1(i, x) for(int i = 1; i <= (x); ++i)
#define RREPname(a, b, c, d, e, ...) e
#define RREP(...) RREPname(__VA_ARGS__, RREP3, RREP2, RREP1, RREP0)(__VA_ARGS__)
#define RREP0(x) for(int i = (x)-1; i >= 0; --i)
#define RREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define RREP2(i, r, l) for(int i = (r)-1; i >= (l); --i)
#define RREP3(i, r, l, c) for(int i = (r)-1; i >= (l); i -= (c))
#define RREPSname(a, b, c, ...) c
#define RREPS(...) RREPSname(__VA_ARGS__, RREPS1, RREPS0)(__VA_ARGS__)
#define RREPS0(x) for(int i = (x); i >= 1; --i)
#define RREPS1(i, x) for(int i = (x); i >= 1; --i)

// name macro
#define pb push_back
#define eb emplace_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define popcnt(x) __builtin_popcountll(x)
template <class T = int>
using V = std::vector<T>;
template <class T = int>
using VV = std::vector<std::vector<T>>;
template <class T>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
using ll = long long;
using ld = long double;
using int128 = __int128_t;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;

// input macro
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
	is >> p.first >> p.second;
	return is;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
	for(T &i : v) is >> i;
	return is;
}
std::istream &operator>>(std::istream &is, __int128_t &a) {
	std::string s;
	is >> s;
	__int128_t ret = 0;
	for(int i = 0; i < s.length(); i++)
		if('0' <= s[i] and s[i] <= '9')
			ret = 10 * ret + s[i] - '0';
	a = ret * (s[0] == '-' ? -1 : 1);
	return is;
}
namespace scanner {
void scan(int &a) { std::cin >> a; }
void scan(long long &a) { std::cin >> a; }
void scan(std::string &a) { std::cin >> a; }
void scan(char &a) { std::cin >> a; }
void scan(char a[]) { std::scanf("%s", a); }
void scan(double &a) { std::cin >> a; }
void scan(long double &a) { std::cin >> a; }
template <class T, class U>
void scan(std::pair<T, U> &p) { std::cin >> p; }
template <class T>
void scan(std::vector<T> &a) { std::cin >> a; }
void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &...tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#define VEC(type, name, size)     \
	std::vector<type> name(size); \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                                    \
	std::vector<std::vector<type>> name(h, std::vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)             \
	std::string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHAR(...)     \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DOUBLE(...)     \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)

// output-macro
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &a) {
	for(int i = 0; i < int(a.size()); ++i) {
		if(i) os << " ";
		os << a[i];
	}
	return os;
}
std::ostream &operator<<(std::ostream &dest, __int128_t &value) {
	std::ostream::sentry s(dest);
	if(s) {
		__uint128_t tmp = value < 0 ? -value : value;
		char buffer[128];
		char *d = std::end(buffer);
		do {
			--d;
			*d = "0123456789"[tmp % 10];
			tmp /= 10;
		} while(tmp != 0);
		if(value < 0) {
			--d;
			*d = '-';
		}
		int len = std::end(buffer) - d;
		if(dest.rdbuf()->sputn(d, len) != len) {
			dest.setstate(std::ios_base::badbit);
		}
	}
	return dest;
}
template <class T>
void print(const T a) { std::cout << a << '\n'; }
template <class Head, class... Tail>
void print(Head H, Tail... T) {
	std::cout << H << ' ';
	print(T...);
}
template <class T>
void printel(const T a) { std::cout << a << '\n'; }
template <class T>
void printel(const std::vector<T> &a) {
	for(const auto &v : a)
		std::cout << v << '\n';
}
template <class Head, class... Tail>
void printel(Head H, Tail... T) {
	std::cout << H << '\n';
	printel(T...);
}
void Yes(const bool b = true) { std::cout << (b ? "Yes\n" : "No\n"); }
void No() { std::cout << "No\n"; }
void YES(const bool b = true) { std::cout << (b ? "YES\n" : "NO\n"); }
void NO() { std::cout << "NO\n"; }
void err(const bool b = true) {
	if(b) {
		std::cout << "-1\n", exit(0);
	}
}

//debug macro
namespace debugger {
template <class T>
void view(const std::vector<T> &a) {
	std::cerr << "{ ";
	for(const auto &v : a) {
		std::cerr << v << ", ";
	}
	std::cerr << "\b\b }";
}
template <class T>
void view(const std::vector<std::vector<T>> &a) {
	std::cerr << "{\n";
	for(const auto &v : a) {
		std::cerr << "\t";
		view(v);
		std::cerr << "\n";
	}
	std::cerr << "}";
}
template <class T, class U>
void view(const std::vector<std::pair<T, U>> &a) {
	std::cerr << "{\n";
	for(const auto &p : a) std::cerr << "\t(" << p.first << ", " << p.second << ")\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &p : m) std::cerr << "\t[" << p.first << "] : " << p.second << "\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::pair<T, U> &p) { std::cerr << "(" << p.first << ", " << p.second << ")"; }
template <class T>
void view(const std::set<T> &s) {
	std::cerr << "{ ";
	for(auto &v : s) {
		view(v);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <class T>
void view(const T &e) { std::cerr << e; }
}  // namespace debugger
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	debugger::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(false)
#else
#define debug(...) (void(0))
#endif

// vector macro
template <class T>
int lb(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::lower_bound((a).begin(), (a).end(), (x))); }
template <class T>
int ub(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::upper_bound((a).begin(), (a).end(), (x))); }
template <class T>
void UNIQUE(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<T> press(std::vector<T> &a) {
	auto res = a;
	UNIQUE(res);
	for(auto &v : a)
		v = lb(res, v);
	return res;
}
#define SORTname(a, b, c, ...) c
#define SORT(...) SORTname(__VA_ARGS__, SORT1, SORT0, ...)(__VA_ARGS__)
#define SORT0(a) std::sort((a).begin(), (a).end())
#define SORT1(a, c) std::sort((a).begin(), (a).end(), [](const auto x, const auto y) { return x c y; })
template <class T>
void ADD(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v += x;
}
template <class T>
void SUB(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v -= x;
}
std::vector<std::pair<char, int>> rle(const string &s) {
	int n = s.size();
	std::vector<std::pair<char, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and s[l] == s[r]; r++) {}
		ret.emplace_back(s[l], r - l);
		l = r;
	}
	return ret;
}
template <class T>
std::vector<std::pair<T, int>> rle(const std::vector<T> &v) {
	int n = v.size();
	std::vector<std::pair<T, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and v[l] == v[r]; r++) {}
		ret.emplace_back(v[l], r - l);
		l = r;
	}
	return ret;
}
std::vector<int> iota(int n) {
	std::vector<int> p(n);
	std::iota(p.begin(), p.end(), 0);
	return p;
}
template <class T>
struct cum_vector {
public:
	cum_vector() = default;
	template <class U>
	cum_vector(const std::vector<U> &vec) : cum((int)vec.size() + 1) {
		for(int i = 0; i < (int)vec.size(); i++)
			cum[i + 1] = cum[i] + vec[i];
	}
	T prod(int l, int r) {
		return cum[r] - cum[l];
	}

private:
	std::vector<T> cum;
};

// math macro
template <class T, class U>
inline bool chmin(T &a, const U &b) { return a > b ? a = b, true : false; }
template <class T, class U>
inline bool chmax(T &a, const U &b) { return a < b ? a = b, true : false; }
template <class T>
T divup(T x, T y) { return (x + y - 1) / y; }
template <class T>
T POW(T a, long long n) {
	T ret = 1;
	while(n) {
		if(n & 1) ret *= a;
		a *= a;
		n >>= 1;
	}
	return ret;
}
// modpow
long long POW(long long a, long long n, const int mod) {
	long long ret = 1;
	a = (a % mod + mod) % mod;
	while(n) {
		if(n & 1) (ret *= a) %= mod;
		(a *= a) %= mod;
		n >>= 1;
	}
	return ret;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f) {
	while(abs(ok - ng) > 1) {
		T mid = (ok + ng) >> 1;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f, int loop) {
	for(int i = 0; i < loop; i++) {
		T mid = (ok + ng) / 2;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}

// others
struct fast_io {
	fast_io() {
		ios::sync_with_stdio(false);
		cin.tie(nullptr);
		cout << fixed << setprecision(15);
	}
} fast_io_;
const int inf = 1e9;
const ll INF = 1e18;
#pragma endregion

void main_();

int main() {
	main_();
	return 0;
}
#line 6 "e.cpp"

map<string, pll> memo;
pll score(string s) {
	if(memo.count(s)) return memo[s];
	if(s.empty()) {
		return memo[s] = {0, 1};
	}
	pll mx = {-inf, 1}, mn = {inf, 1};
	bool has_b = 0, has_w = 0;
	RREP(i, SZ(s)) {
		if(s[i] == 'B') {
			has_b = 1;
			auto c = s;
			c.resize(i);
			auto nx = score(c);
			if((int128)mx.first * nx.second < (int128)mx.second * nx.first) mx = nx;
		} else {
			has_w = 1;
			auto c = s;
			c.resize(i);
			auto nx = score(c);
			if((int128)mn.first * nx.second > (int128)mn.second * nx.first) mn = nx;
		}
	}
	if(!has_b) {
		mn.first -= mn.second;
		return memo[s] = mn;
	}
	if(!has_w) {
		mx.first += mx.second;
		return memo[s] = mx;
	}
	//1/4以上 1/2

	REP(j, 40) {
		int128 lef = divup((int128)mx.first * (1ll << j), (int128)mx.second);
		if(mx.first < 0) {
			lef = (int128)mx.first * (1ll << j) / mx.second;
		}
		if(((int128)mx.first * (1ll << j)) % mx.second == 0) lef++;
		int128 rig = (int128)mn.first * (1ll << j) / mn.second;
		if(mn.first < 0 and (int128) mn.first * (1ll << j) % mn.second) rig--;
		if(((int128)mn.first * (1ll << j)) % mn.second == 0) rig--;
		if(lef > rig) continue;
		if(lef * rig <= 0) {
			return memo[s] = {0, 1};
		} else {
			if(abs((ll)lef) <= abs((ll)rig)) {
				return memo[s] = {lef, 1ll << j};
			} else {
				return memo[s] = {rig, 1ll << j};
			}
		}
	}
	return {0, 0};
}

void main_() {
	INT(n);
	VEC(string, s, n);
	V<ll> wei(n);
	REP(i, n) {
		auto p = score(s[i]);
		while(p.second < (1ll << 40)) {
			p.first <<= 1;
			p.second <<= 1;
		}
		wei[i] = p.first;
	}

	debug(wei);

	if(n <= 20) {
		int res = 0;
		REP(bit, 1 << n) {
			ll sum = 0, val = 0;
			REP(i, n) {
				if(bit >> i & 1) {
					sum += wei[i];
					val += SZ(s[i]);
				}
			}
			if(sum == 0) {
				chmax(res, val);
			}
		}
		print(res);
	} else {
		unordered_map<ll, int> mp;
		int res = 0;
		REP(bit, 1 << 20) {
			ll sum = 0, val = 0;
			REP(i, 20) {
				if(bit >> i & 1) {
					sum += wei[i];
					val += SZ(s[i]);
				}
			}
			chmax(mp[sum], val);
		}
		REP(bit, 1 << (n - 20)) {
			ll sum = 0, val = 0;
			REP(i, n - 20) {
				if(bit >> i & 1) {
					sum += wei[i + 20];
					val += SZ(s[i + 20]);
				}
			}
			if(mp.count(-sum)) {
				chmax(res, val + mp[-sum]);
			}
		}
		print(res);
	}
}
accuracy: 1
time_ms: 370
memory_kb: 52836
final_rank: 4

code_snippet: #line 1 "e.cpp"
/**
 *	author: nok0
 *	created: 2022.04.06 15:16:23
**/
#line 1 "/Users/nok0/Documents/Programming/nok0/cftemp.hpp"
#include <bits/stdc++.h>
using namespace std;

#pragma region Macros
// rep macro
#define foa(v, a) for(auto &v : a)
#define REPname(a, b, c, d, e, ...) e
#define REP(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int i = 0; i < (x); ++i)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define REPSname(a, b, c, ...) c
#define REPS(...) REPSname(__VA_ARGS__, REPS1, REPS0)(__VA_ARGS__)
#define REPS0(x) for(int i = 1; i <= (x); ++i)
#define REPS1(i, x) for(int i = 1; i <= (x); ++i)
#define RREPname(a, b, c, d, e, ...) e
#define RREP(...) RREPname(__VA_ARGS__, RREP3, RREP2, RREP1, RREP0)(__VA_ARGS__)
#define RREP0(x) for(int i = (x)-1; i >= 0; --i)
#define RREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define RREP2(i, r, l) for(int i = (r)-1; i >= (l); --i)
#define RREP3(i, r, l, c) for(int i = (r)-1; i >= (l); i -= (c))
#define RREPSname(a, b, c, ...) c
#define RREPS(...) RREPSname(__VA_ARGS__, RREPS1, RREPS0)(__VA_ARGS__)
#define RREPS0(x) for(int i = (x); i >= 1; --i)
#define RREPS1(i, x) for(int i = (x); i >= 1; --i)

// name macro
#define pb push_back
#define eb emplace_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define popcnt(x) __builtin_popcountll(x)
template <class T = int>
using V = std::vector<T>;
template <class T = int>
using VV = std::vector<std::vector<T>>;
template <class T>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
using ll = long long;
using ld = long double;
using int128 = __int128_t;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;

// input macro
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
	is >> p.first >> p.second;
	return is;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
	for(T &i : v) is >> i;
	return is;
}
std::istream &operator>>(std::istream &is, __int128_t &a) {
	std::string s;
	is >> s;
	__int128_t ret = 0;
	for(int i = 0; i < s.length(); i++)
		if('0' <= s[i] and s[i] <= '9')
			ret = 10 * ret + s[i] - '0';
	a = ret * (s[0] == '-' ? -1 : 1);
	return is;
}
namespace scanner {
void scan(int &a) { std::cin >> a; }
void scan(long long &a) { std::cin >> a; }
void scan(std::string &a) { std::cin >> a; }
void scan(char &a) { std::cin >> a; }
void scan(char a[]) { std::scanf("%s", a); }
void scan(double &a) { std::cin >> a; }
void scan(long double &a) { std::cin >> a; }
template <class T, class U>
void scan(std::pair<T, U> &p) { std::cin >> p; }
template <class T>
void scan(std::vector<T> &a) { std::cin >> a; }
void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &...tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#define VEC(type, name, size)     \
	std::vector<type> name(size); \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                                    \
	std::vector<std::vector<type>> name(h, std::vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)             \
	std::string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHAR(...)     \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DOUBLE(...)     \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)

// output-macro
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &a) {
	for(int i = 0; i < int(a.size()); ++i) {
		if(i) os << " ";
		os << a[i];
	}
	return os;
}
std::ostream &operator<<(std::ostream &dest, __int128_t &value) {
	std::ostream::sentry s(dest);
	if(s) {
		__uint128_t tmp = value < 0 ? -value : value;
		char buffer[128];
		char *d = std::end(buffer);
		do {
			--d;
			*d = "0123456789"[tmp % 10];
			tmp /= 10;
		} while(tmp != 0);
		if(value < 0) {
			--d;
			*d = '-';
		}
		int len = std::end(buffer) - d;
		if(dest.rdbuf()->sputn(d, len) != len) {
			dest.setstate(std::ios_base::badbit);
		}
	}
	return dest;
}
template <class T>
void print(const T a) { std::cout << a << '\n'; }
template <class Head, class... Tail>
void print(Head H, Tail... T) {
	std::cout << H << ' ';
	print(T...);
}
template <class T>
void printel(const T a) { std::cout << a << '\n'; }
template <class T>
void printel(const std::vector<T> &a) {
	for(const auto &v : a)
		std::cout << v << '\n';
}
template <class Head, class... Tail>
void printel(Head H, Tail... T) {
	std::cout << H << '\n';
	printel(T...);
}
void Yes(const bool b = true) { std::cout << (b ? "Yes\n" : "No\n"); }
void No() { std::cout << "No\n"; }
void YES(const bool b = true) { std::cout << (b ? "YES\n" : "NO\n"); }
void NO() { std::cout << "NO\n"; }
void err(const bool b = true) {
	if(b) {
		std::cout << "-1\n", exit(0);
	}
}

//debug macro
namespace debugger {
template <class T>
void view(const std::vector<T> &a) {
	std::cerr << "{ ";
	for(const auto &v : a) {
		std::cerr << v << ", ";
	}
	std::cerr << "\b\b }";
}
template <class T>
void view(const std::vector<std::vector<T>> &a) {
	std::cerr << "{\n";
	for(const auto &v : a) {
		std::cerr << "\t";
		view(v);
		std::cerr << "\n";
	}
	std::cerr << "}";
}
template <class T, class U>
void view(const std::vector<std::pair<T, U>> &a) {
	std::cerr << "{\n";
	for(const auto &p : a) std::cerr << "\t(" << p.first << ", " << p.second << ")\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &p : m) std::cerr << "\t[" << p.first << "] : " << p.second << "\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::pair<T, U> &p) { std::cerr << "(" << p.first << ", " << p.second << ")"; }
template <class T>
void view(const std::set<T> &s) {
	std::cerr << "{ ";
	for(auto &v : s) {
		view(v);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <class T>
void view(const T &e) { std::cerr << e; }
}  // namespace debugger
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	debugger::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(false)
#else
#define debug(...) (void(0))
#endif

// vector macro
template <class T>
int lb(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::lower_bound((a).begin(), (a).end(), (x))); }
template <class T>
int ub(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::upper_bound((a).begin(), (a).end(), (x))); }
template <class T>
void UNIQUE(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<T> press(std::vector<T> &a) {
	auto res = a;
	UNIQUE(res);
	for(auto &v : a)
		v = lb(res, v);
	return res;
}
#define SORTname(a, b, c, ...) c
#define SORT(...) SORTname(__VA_ARGS__, SORT1, SORT0, ...)(__VA_ARGS__)
#define SORT0(a) std::sort((a).begin(), (a).end())
#define SORT1(a, c) std::sort((a).begin(), (a).end(), [](const auto x, const auto y) { return x c y; })
template <class T>
void ADD(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v += x;
}
template <class T>
void SUB(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v -= x;
}
std::vector<std::pair<char, int>> rle(const string &s) {
	int n = s.size();
	std::vector<std::pair<char, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and s[l] == s[r]; r++) {}
		ret.emplace_back(s[l], r - l);
		l = r;
	}
	return ret;
}
template <class T>
std::vector<std::pair<T, int>> rle(const std::vector<T> &v) {
	int n = v.size();
	std::vector<std::pair<T, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and v[l] == v[r]; r++) {}
		ret.emplace_back(v[l], r - l);
		l = r;
	}
	return ret;
}
std::vector<int> iota(int n) {
	std::vector<int> p(n);
	std::iota(p.begin(), p.end(), 0);
	return p;
}
template <class T>
struct cum_vector {
public:
	cum_vector() = default;
	template <class U>
	cum_vector(const std::vector<U> &vec) : cum((int)vec.size() + 1) {
		for(int i = 0; i < (int)vec.size(); i++)
			cum[i + 1] = cum[i] + vec[i];
	}
	T prod(int l, int r) {
		return cum[r] - cum[l];
	}

private:
	std::vector<T> cum;
};

// math macro
template <class T, class U>
inline bool chmin(T &a, const U &b) { return a > b ? a = b, true : false; }
template <class T, class U>
inline bool chmax(T &a, const U &b) { return a < b ? a = b, true : false; }
template <class T>
T divup(T x, T y) { return (x + y - 1) / y; }
template <class T>
T POW(T a, long long n) {
	T ret = 1;
	while(n) {
		if(n & 1) ret *= a;
		a *= a;
		n >>= 1;
	}
	return ret;
}
// modpow
long long POW(long long a, long long n, const int mod) {
	long long ret = 1;
	a = (a % mod + mod) % mod;
	while(n) {
		if(n & 1) (ret *= a) %= mod;
		(a *= a) %= mod;
		n >>= 1;
	}
	return ret;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f) {
	while(abs(ok - ng) > 1) {
		T mid = (ok + ng) >> 1;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f, int loop) {
	for(int i = 0; i < loop; i++) {
		T mid = (ok + ng) / 2;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}

// others
struct fast_io {
	fast_io() {
		ios::sync_with_stdio(false);
		cin.tie(nullptr);
		cout << fixed << setprecision(15);
	}
} fast_io_;
const int inf = 1e9;
const ll INF = 1e18;
#pragma endregion

void main_();

int main() {
	main_();
	return 0;
}
#line 6 "e.cpp"

map<string, pll> memo;
pll score(string s) {
	if(memo.count(s)) return memo[s];
	if(s.empty()) {
		return memo[s] = {0, 1};
	}
	pll mx = {-inf, 1}, mn = {inf, 1};
	bool has_b = 0, has_w = 0;
	RREP(i, SZ(s)) {
		if(s[i] == 'B') {
			has_b = 1;
			auto c = s;
			c.resize(i);
			auto nx = score(c);
			if((int128)mx.first * nx.second < (int128)mx.second * nx.first) mx = nx;
		} else {
			has_w = 1;
			auto c = s;
			c.resize(i);
			auto nx = score(c);
			if((int128)mn.first * nx.second > (int128)mn.second * nx.first) mn = nx;
		}
	}
	if(!has_b) {
		mn.first -= mn.second;
		return memo[s] = mn;
	}
	if(!has_w) {
		mx.first += mx.second;
		return memo[s] = mx;
	}
	//1/4以上 1/2

	REP(j, 40) {
		ll lef = divup(mx.first * (1ll << j), mx.second);
		if(mx.first < 0) {
			lef = mx.first * (1ll << j) / mx.second;
		}
		if((mx.first * (1ll << j)) % mx.second == 0) lef++;
		ll rig = mn.first * (1ll << j) / mn.second;
		if(mn.first < 0 and mn.first * (1ll << j) % mn.second) rig--;
		if((mn.first * (1ll << j)) % mn.second == 0) rig--;
		if(lef > rig) continue;
		if(lef * rig <= 0) {
			return memo[s] = {0, 1};
		} else {
			if(abs(lef) <= abs(rig)) {
				return memo[s] = {lef, 1ll << j};
			} else {
				return memo[s] = {rig, 1ll << j};
			}
		}
	}
	return {0, 0};
}

void main_() {
	INT(n);
	VEC(string, s, n);
	V<ll> wei(n);
	REP(i, n) {
		auto p = score(s[i]);
		while(p.second < (1ll << 40)) {
			p.first <<= 1;
			p.second <<= 1;
		}
		wei[i] = p.first;
	}

	debug(wei);

	if(n <= 20) {
		int res = 0;
		REP(bit, 1 << n) {
			ll sum = 0, val = 0;
			REP(i, n) {
				if(bit >> i & 1) {
					sum += wei[i];
					val += SZ(s[i]);
				}
			}
			if(sum == 0) {
				chmax(res, val);
			}
		}
		print(res);
	} else {
		unordered_map<ll, int> mp;
		int res = 0;
		REP(bit, 1 << 20) {
			ll sum = 0, val = 0;
			REP(i, 20) {
				if(bit >> i & 1) {
					sum += wei[i];
					val += SZ(s[i]);
				}
			}
			chmax(mp[sum], val);
		}
		REP(bit, 1 << (n - 20)) {
			ll sum = 0, val = 0;
			REP(i, n - 20) {
				if(bit >> i & 1) {
					sum += wei[i + 20];
					val += SZ(s[i + 20]);
				}
			}
			if(mp.count(-sum)) {
				chmax(res, val + mp[-sum]);
			}
		}
		print(res);
	}
}
accuracy: 0.8636363636363636
time_ms: 320
memory_kb: 52904
final_rank: 13

code_snippet: #line 1 "e.cpp"
/**
 *	author: nok0
 *	created: 2022.04.06 15:16:23
**/
#line 1 "/Users/nok0/Documents/Programming/nok0/cftemp.hpp"
#include <bits/stdc++.h>
using namespace std;

#pragma region Macros
// rep macro
#define foa(v, a) for(auto &v : a)
#define REPname(a, b, c, d, e, ...) e
#define REP(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int i = 0; i < (x); ++i)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define REPSname(a, b, c, ...) c
#define REPS(...) REPSname(__VA_ARGS__, REPS1, REPS0)(__VA_ARGS__)
#define REPS0(x) for(int i = 1; i <= (x); ++i)
#define REPS1(i, x) for(int i = 1; i <= (x); ++i)
#define RREPname(a, b, c, d, e, ...) e
#define RREP(...) RREPname(__VA_ARGS__, RREP3, RREP2, RREP1, RREP0)(__VA_ARGS__)
#define RREP0(x) for(int i = (x)-1; i >= 0; --i)
#define RREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define RREP2(i, r, l) for(int i = (r)-1; i >= (l); --i)
#define RREP3(i, r, l, c) for(int i = (r)-1; i >= (l); i -= (c))
#define RREPSname(a, b, c, ...) c
#define RREPS(...) RREPSname(__VA_ARGS__, RREPS1, RREPS0)(__VA_ARGS__)
#define RREPS0(x) for(int i = (x); i >= 1; --i)
#define RREPS1(i, x) for(int i = (x); i >= 1; --i)

// name macro
#define pb push_back
#define eb emplace_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define popcnt(x) __builtin_popcountll(x)
template <class T = int>
using V = std::vector<T>;
template <class T = int>
using VV = std::vector<std::vector<T>>;
template <class T>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
using ll = long long;
using ld = long double;
using int128 = __int128_t;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;

// input macro
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
	is >> p.first >> p.second;
	return is;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
	for(T &i : v) is >> i;
	return is;
}
std::istream &operator>>(std::istream &is, __int128_t &a) {
	std::string s;
	is >> s;
	__int128_t ret = 0;
	for(int i = 0; i < s.length(); i++)
		if('0' <= s[i] and s[i] <= '9')
			ret = 10 * ret + s[i] - '0';
	a = ret * (s[0] == '-' ? -1 : 1);
	return is;
}
namespace scanner {
void scan(int &a) { std::cin >> a; }
void scan(long long &a) { std::cin >> a; }
void scan(std::string &a) { std::cin >> a; }
void scan(char &a) { std::cin >> a; }
void scan(char a[]) { std::scanf("%s", a); }
void scan(double &a) { std::cin >> a; }
void scan(long double &a) { std::cin >> a; }
template <class T, class U>
void scan(std::pair<T, U> &p) { std::cin >> p; }
template <class T>
void scan(std::vector<T> &a) { std::cin >> a; }
void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &...tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#define VEC(type, name, size)     \
	std::vector<type> name(size); \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                                    \
	std::vector<std::vector<type>> name(h, std::vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)             \
	std::string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHAR(...)     \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DOUBLE(...)     \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)

// output-macro
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &a) {
	for(int i = 0; i < int(a.size()); ++i) {
		if(i) os << " ";
		os << a[i];
	}
	return os;
}
std::ostream &operator<<(std::ostream &dest, __int128_t &value) {
	std::ostream::sentry s(dest);
	if(s) {
		__uint128_t tmp = value < 0 ? -value : value;
		char buffer[128];
		char *d = std::end(buffer);
		do {
			--d;
			*d = "0123456789"[tmp % 10];
			tmp /= 10;
		} while(tmp != 0);
		if(value < 0) {
			--d;
			*d = '-';
		}
		int len = std::end(buffer) - d;
		if(dest.rdbuf()->sputn(d, len) != len) {
			dest.setstate(std::ios_base::badbit);
		}
	}
	return dest;
}
template <class T>
void print(const T a) { std::cout << a << '\n'; }
template <class Head, class... Tail>
void print(Head H, Tail... T) {
	std::cout << H << ' ';
	print(T...);
}
template <class T>
void printel(const T a) { std::cout << a << '\n'; }
template <class T>
void printel(const std::vector<T> &a) {
	for(const auto &v : a)
		std::cout << v << '\n';
}
template <class Head, class... Tail>
void printel(Head H, Tail... T) {
	std::cout << H << '\n';
	printel(T...);
}
void Yes(const bool b = true) { std::cout << (b ? "Yes\n" : "No\n"); }
void No() { std::cout << "No\n"; }
void YES(const bool b = true) { std::cout << (b ? "YES\n" : "NO\n"); }
void NO() { std::cout << "NO\n"; }
void err(const bool b = true) {
	if(b) {
		std::cout << "-1\n", exit(0);
	}
}

//debug macro
namespace debugger {
template <class T>
void view(const std::vector<T> &a) {
	std::cerr << "{ ";
	for(const auto &v : a) {
		std::cerr << v << ", ";
	}
	std::cerr << "\b\b }";
}
template <class T>
void view(const std::vector<std::vector<T>> &a) {
	std::cerr << "{\n";
	for(const auto &v : a) {
		std::cerr << "\t";
		view(v);
		std::cerr << "\n";
	}
	std::cerr << "}";
}
template <class T, class U>
void view(const std::vector<std::pair<T, U>> &a) {
	std::cerr << "{\n";
	for(const auto &p : a) std::cerr << "\t(" << p.first << ", " << p.second << ")\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &p : m) std::cerr << "\t[" << p.first << "] : " << p.second << "\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::pair<T, U> &p) { std::cerr << "(" << p.first << ", " << p.second << ")"; }
template <class T>
void view(const std::set<T> &s) {
	std::cerr << "{ ";
	for(auto &v : s) {
		view(v);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <class T>
void view(const T &e) { std::cerr << e; }
}  // namespace debugger
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	debugger::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(false)
#else
#define debug(...) (void(0))
#endif

// vector macro
template <class T>
int lb(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::lower_bound((a).begin(), (a).end(), (x))); }
template <class T>
int ub(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::upper_bound((a).begin(), (a).end(), (x))); }
template <class T>
void UNIQUE(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<T> press(std::vector<T> &a) {
	auto res = a;
	UNIQUE(res);
	for(auto &v : a)
		v = lb(res, v);
	return res;
}
#define SORTname(a, b, c, ...) c
#define SORT(...) SORTname(__VA_ARGS__, SORT1, SORT0, ...)(__VA_ARGS__)
#define SORT0(a) std::sort((a).begin(), (a).end())
#define SORT1(a, c) std::sort((a).begin(), (a).end(), [](const auto x, const auto y) { return x c y; })
template <class T>
void ADD(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v += x;
}
template <class T>
void SUB(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v -= x;
}
std::vector<std::pair<char, int>> rle(const string &s) {
	int n = s.size();
	std::vector<std::pair<char, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and s[l] == s[r]; r++) {}
		ret.emplace_back(s[l], r - l);
		l = r;
	}
	return ret;
}
template <class T>
std::vector<std::pair<T, int>> rle(const std::vector<T> &v) {
	int n = v.size();
	std::vector<std::pair<T, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and v[l] == v[r]; r++) {}
		ret.emplace_back(v[l], r - l);
		l = r;
	}
	return ret;
}
std::vector<int> iota(int n) {
	std::vector<int> p(n);
	std::iota(p.begin(), p.end(), 0);
	return p;
}
template <class T>
struct cum_vector {
public:
	cum_vector() = default;
	template <class U>
	cum_vector(const std::vector<U> &vec) : cum((int)vec.size() + 1) {
		for(int i = 0; i < (int)vec.size(); i++)
			cum[i + 1] = cum[i] + vec[i];
	}
	T prod(int l, int r) {
		return cum[r] - cum[l];
	}

private:
	std::vector<T> cum;
};

// math macro
template <class T, class U>
inline bool chmin(T &a, const U &b) { return a > b ? a = b, true : false; }
template <class T, class U>
inline bool chmax(T &a, const U &b) { return a < b ? a = b, true : false; }
template <class T>
T divup(T x, T y) { return (x + y - 1) / y; }
template <class T>
T POW(T a, long long n) {
	T ret = 1;
	while(n) {
		if(n & 1) ret *= a;
		a *= a;
		n >>= 1;
	}
	return ret;
}
// modpow
long long POW(long long a, long long n, const int mod) {
	long long ret = 1;
	a = (a % mod + mod) % mod;
	while(n) {
		if(n & 1) (ret *= a) %= mod;
		(a *= a) %= mod;
		n >>= 1;
	}
	return ret;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f) {
	while(abs(ok - ng) > 1) {
		T mid = (ok + ng) >> 1;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f, int loop) {
	for(int i = 0; i < loop; i++) {
		T mid = (ok + ng) / 2;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}

// others
struct fast_io {
	fast_io() {
		ios::sync_with_stdio(false);
		cin.tie(nullptr);
		cout << fixed << setprecision(15);
	}
} fast_io_;
const int inf = 1e9;
const ll INF = 1e18;
#pragma endregion

void main_();

int main() {
	main_();
	return 0;
}
#line 6 "e.cpp"

map<string, pll> memo;
pll score(string s) {
	if(memo.count(s)) return memo[s];
	if(s.empty()) {
		return memo[s] = {0, 1};
	}
	pll mx = {-inf, 1}, mn = {inf, 1};
	bool has_b = 0, has_w = 0;
	RREP(i, SZ(s)) {
		if(s[i] == 'B') {
			has_b = 1;
			auto c = s;
			c.resize(i);
			auto nx = score(c);
			if(mx.first * nx.second < mx.second * nx.first) mx = nx;
		} else {
			has_w = 1;
			auto c = s;
			c.resize(i);
			auto nx = score(c);
			if(mn.first * nx.second > mn.second * nx.first) mn = nx;
		}
	}
	if(!has_b) {
		mn.first -= mn.second;
		return memo[s] = mn;
	}
	if(!has_w) {
		mx.first += mx.second;
		return memo[s] = mx;
	}
	//1/4以上 1/2

	REP(j, 40) {
		ll lef = divup(mx.first * (1ll << j), mx.second);
		if(mx.first < 0) {
			lef = mx.first * (1ll << j) / mx.second;
		}
		if((mx.first * (1ll << j)) % mx.second == 0) lef++;
		ll rig = mn.first * (1ll << j) / mn.second;
		if(mn.first < 0 and mn.first * (1ll << j) % mn.second) rig--;
		if((mn.first * (1ll << j)) % mn.second == 0) rig--;
		if(lef > rig) continue;
		if(lef * rig <= 0) {
			return memo[s] = {0, 1};
		} else {
			if(abs(lef) <= abs(rig)) {
				return memo[s] = {lef, 1ll << j};
			} else {
				return memo[s] = {rig, 1ll << j};
			}
		}
	}
	return {0, 0};
}

void main_() {
	INT(n);
	VEC(string, s, n);
	V<ll> wei(n);
	REP(i, n) {
		auto p = score(s[i]);
		while(p.second < (1ll << 40)) {
			p.first <<= 1;
			p.second <<= 1;
		}
		wei[i] = p.first;
	}

	if(n <= 20) {
		int res = 0;
		REP(bit, 1 << n) {
			ll sum = 0, val = 0;
			REP(i, n) {
				if(bit >> i & 1) {
					sum += wei[i];
					val += SZ(s[i]);
				}
			}
			if(sum == 0) {
				chmax(res, val);
			}
		}
		print(res);
	} else {
		unordered_map<ll, int> mp;
		int res = 0;
		REP(bit, 1 << 20) {
			ll sum = 0, val = 0;
			REP(i, 20) {
				if(bit >> i & 1) {
					sum += wei[i];
					val += SZ(s[i]);
				}
			}
			chmax(mp[sum], val);
		}
		REP(bit, 1 << (n - 20)) {
			ll sum = 0, val = 0;
			REP(i, n - 20) {
				if(bit >> i & 1) {
					sum += wei[i + 20];
					val += SZ(s[i + 20]);
				}
			}
			if(mp.count(-sum)) {
				chmax(res, val + mp[-sum]);
			}
		}
		print(res);
	}
}
accuracy: 0.045454545454545456
time_ms: 240
memory_kb: 52680
final_rank: 18

code_snippet: #line 1 "e.cpp"
/**
 *	author: nok0
 *	created: 2022.04.06 15:16:23
**/
#line 1 "/Users/nok0/Documents/Programming/nok0/cftemp.hpp"
#include <bits/stdc++.h>
using namespace std;

#pragma region Macros
// rep macro
#define foa(v, a) for(auto &v : a)
#define REPname(a, b, c, d, e, ...) e
#define REP(...) REPname(__VA_ARGS__, REP3, REP2, REP1, REP0)(__VA_ARGS__)
#define REP0(x) for(int i = 0; i < (x); ++i)
#define REP1(i, x) for(int i = 0; i < (x); ++i)
#define REP2(i, l, r) for(int i = (l); i < (r); ++i)
#define REP3(i, l, r, c) for(int i = (l); i < (r); i += (c))
#define REPSname(a, b, c, ...) c
#define REPS(...) REPSname(__VA_ARGS__, REPS1, REPS0)(__VA_ARGS__)
#define REPS0(x) for(int i = 1; i <= (x); ++i)
#define REPS1(i, x) for(int i = 1; i <= (x); ++i)
#define RREPname(a, b, c, d, e, ...) e
#define RREP(...) RREPname(__VA_ARGS__, RREP3, RREP2, RREP1, RREP0)(__VA_ARGS__)
#define RREP0(x) for(int i = (x)-1; i >= 0; --i)
#define RREP1(i, x) for(int i = (x)-1; i >= 0; --i)
#define RREP2(i, r, l) for(int i = (r)-1; i >= (l); --i)
#define RREP3(i, r, l, c) for(int i = (r)-1; i >= (l); i -= (c))
#define RREPSname(a, b, c, ...) c
#define RREPS(...) RREPSname(__VA_ARGS__, RREPS1, RREPS0)(__VA_ARGS__)
#define RREPS0(x) for(int i = (x); i >= 1; --i)
#define RREPS1(i, x) for(int i = (x); i >= 1; --i)

// name macro
#define pb push_back
#define eb emplace_back
#define SZ(x) ((int)(x).size())
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
#define popcnt(x) __builtin_popcountll(x)
template <class T = int>
using V = std::vector<T>;
template <class T = int>
using VV = std::vector<std::vector<T>>;
template <class T>
using pqup = std::priority_queue<T, std::vector<T>, std::greater<T>>;
using ll = long long;
using ld = long double;
using int128 = __int128_t;
using pii = std::pair<int, int>;
using pll = std::pair<long long, long long>;

// input macro
template <class T, class U>
std::istream &operator>>(std::istream &is, std::pair<T, U> &p) {
	is >> p.first >> p.second;
	return is;
}
template <class T>
std::istream &operator>>(std::istream &is, std::vector<T> &v) {
	for(T &i : v) is >> i;
	return is;
}
std::istream &operator>>(std::istream &is, __int128_t &a) {
	std::string s;
	is >> s;
	__int128_t ret = 0;
	for(int i = 0; i < s.length(); i++)
		if('0' <= s[i] and s[i] <= '9')
			ret = 10 * ret + s[i] - '0';
	a = ret * (s[0] == '-' ? -1 : 1);
	return is;
}
namespace scanner {
void scan(int &a) { std::cin >> a; }
void scan(long long &a) { std::cin >> a; }
void scan(std::string &a) { std::cin >> a; }
void scan(char &a) { std::cin >> a; }
void scan(char a[]) { std::scanf("%s", a); }
void scan(double &a) { std::cin >> a; }
void scan(long double &a) { std::cin >> a; }
template <class T, class U>
void scan(std::pair<T, U> &p) { std::cin >> p; }
template <class T>
void scan(std::vector<T> &a) { std::cin >> a; }
void INPUT() {}
template <class Head, class... Tail>
void INPUT(Head &head, Tail &...tail) {
	scan(head);
	INPUT(tail...);
}
}  // namespace scanner
#define VEC(type, name, size)     \
	std::vector<type> name(size); \
	scanner::INPUT(name)
#define VVEC(type, name, h, w)                                    \
	std::vector<std::vector<type>> name(h, std::vector<type>(w)); \
	scanner::INPUT(name)
#define INT(...)     \
	int __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LL(...)            \
	long long __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define STR(...)             \
	std::string __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define CHAR(...)     \
	char __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define DOUBLE(...)     \
	double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)
#define LD(...)              \
	long double __VA_ARGS__; \
	scanner::INPUT(__VA_ARGS__)

// output-macro
template <class T, class U>
std::ostream &operator<<(std::ostream &os, const std::pair<T, U> &p) {
	os << p.first << " " << p.second;
	return os;
}
template <class T>
std::ostream &operator<<(std::ostream &os, const std::vector<T> &a) {
	for(int i = 0; i < int(a.size()); ++i) {
		if(i) os << " ";
		os << a[i];
	}
	return os;
}
std::ostream &operator<<(std::ostream &dest, __int128_t &value) {
	std::ostream::sentry s(dest);
	if(s) {
		__uint128_t tmp = value < 0 ? -value : value;
		char buffer[128];
		char *d = std::end(buffer);
		do {
			--d;
			*d = "0123456789"[tmp % 10];
			tmp /= 10;
		} while(tmp != 0);
		if(value < 0) {
			--d;
			*d = '-';
		}
		int len = std::end(buffer) - d;
		if(dest.rdbuf()->sputn(d, len) != len) {
			dest.setstate(std::ios_base::badbit);
		}
	}
	return dest;
}
template <class T>
void print(const T a) { std::cout << a << '\n'; }
template <class Head, class... Tail>
void print(Head H, Tail... T) {
	std::cout << H << ' ';
	print(T...);
}
template <class T>
void printel(const T a) { std::cout << a << '\n'; }
template <class T>
void printel(const std::vector<T> &a) {
	for(const auto &v : a)
		std::cout << v << '\n';
}
template <class Head, class... Tail>
void printel(Head H, Tail... T) {
	std::cout << H << '\n';
	printel(T...);
}
void Yes(const bool b = true) { std::cout << (b ? "Yes\n" : "No\n"); }
void No() { std::cout << "No\n"; }
void YES(const bool b = true) { std::cout << (b ? "YES\n" : "NO\n"); }
void NO() { std::cout << "NO\n"; }
void err(const bool b = true) {
	if(b) {
		std::cout << "-1\n", exit(0);
	}
}

//debug macro
namespace debugger {
template <class T>
void view(const std::vector<T> &a) {
	std::cerr << "{ ";
	for(const auto &v : a) {
		std::cerr << v << ", ";
	}
	std::cerr << "\b\b }";
}
template <class T>
void view(const std::vector<std::vector<T>> &a) {
	std::cerr << "{\n";
	for(const auto &v : a) {
		std::cerr << "\t";
		view(v);
		std::cerr << "\n";
	}
	std::cerr << "}";
}
template <class T, class U>
void view(const std::vector<std::pair<T, U>> &a) {
	std::cerr << "{\n";
	for(const auto &p : a) std::cerr << "\t(" << p.first << ", " << p.second << ")\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::map<T, U> &m) {
	std::cerr << "{\n";
	for(const auto &p : m) std::cerr << "\t[" << p.first << "] : " << p.second << "\n";
	std::cerr << "}";
}
template <class T, class U>
void view(const std::pair<T, U> &p) { std::cerr << "(" << p.first << ", " << p.second << ")"; }
template <class T>
void view(const std::set<T> &s) {
	std::cerr << "{ ";
	for(auto &v : s) {
		view(v);
		std::cerr << ", ";
	}
	std::cerr << "\b\b }";
}

template <class T>
void view(const T &e) { std::cerr << e; }
}  // namespace debugger
#ifdef LOCAL
void debug_out() {}
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
	debugger::view(H);
	std::cerr << ", ";
	debug_out(T...);
}
#define debug(...)                                                \
	do {                                                          \
		std::cerr << __LINE__ << " [" << #__VA_ARGS__ << "] : ["; \
		debug_out(__VA_ARGS__);                                   \
		std::cerr << "\b\b]\n";                                   \
	} while(false)
#else
#define debug(...) (void(0))
#endif

// vector macro
template <class T>
int lb(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::lower_bound((a).begin(), (a).end(), (x))); }
template <class T>
int ub(const std::vector<T> &a, const T x) { return std::distance((a).begin(), std::upper_bound((a).begin(), (a).end(), (x))); }
template <class T>
void UNIQUE(std::vector<T> &a) {
	std::sort(a.begin(), a.end());
	a.erase(std::unique(a.begin(), a.end()), a.end());
}
template <class T>
std::vector<T> press(std::vector<T> &a) {
	auto res = a;
	UNIQUE(res);
	for(auto &v : a)
		v = lb(res, v);
	return res;
}
#define SORTname(a, b, c, ...) c
#define SORT(...) SORTname(__VA_ARGS__, SORT1, SORT0, ...)(__VA_ARGS__)
#define SORT0(a) std::sort((a).begin(), (a).end())
#define SORT1(a, c) std::sort((a).begin(), (a).end(), [](const auto x, const auto y) { return x c y; })
template <class T>
void ADD(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v += x;
}
template <class T>
void SUB(std::vector<T> &a, const T x = 1) {
	for(auto &v : a) v -= x;
}
std::vector<std::pair<char, int>> rle(const string &s) {
	int n = s.size();
	std::vector<std::pair<char, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and s[l] == s[r]; r++) {}
		ret.emplace_back(s[l], r - l);
		l = r;
	}
	return ret;
}
template <class T>
std::vector<std::pair<T, int>> rle(const std::vector<T> &v) {
	int n = v.size();
	std::vector<std::pair<T, int>> ret;
	for(int l = 0; l < n;) {
		int r = l + 1;
		for(; r < n and v[l] == v[r]; r++) {}
		ret.emplace_back(v[l], r - l);
		l = r;
	}
	return ret;
}
std::vector<int> iota(int n) {
	std::vector<int> p(n);
	std::iota(p.begin(), p.end(), 0);
	return p;
}
template <class T>
struct cum_vector {
public:
	cum_vector() = default;
	template <class U>
	cum_vector(const std::vector<U> &vec) : cum((int)vec.size() + 1) {
		for(int i = 0; i < (int)vec.size(); i++)
			cum[i + 1] = cum[i] + vec[i];
	}
	T prod(int l, int r) {
		return cum[r] - cum[l];
	}

private:
	std::vector<T> cum;
};

// math macro
template <class T, class U>
inline bool chmin(T &a, const U &b) { return a > b ? a = b, true : false; }
template <class T, class U>
inline bool chmax(T &a, const U &b) { return a < b ? a = b, true : false; }
template <class T>
T divup(T x, T y) { return (x + y - 1) / y; }
template <class T>
T POW(T a, long long n) {
	T ret = 1;
	while(n) {
		if(n & 1) ret *= a;
		a *= a;
		n >>= 1;
	}
	return ret;
}
// modpow
long long POW(long long a, long long n, const int mod) {
	long long ret = 1;
	a = (a % mod + mod) % mod;
	while(n) {
		if(n & 1) (ret *= a) %= mod;
		(a *= a) %= mod;
		n >>= 1;
	}
	return ret;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f) {
	while(abs(ok - ng) > 1) {
		T mid = (ok + ng) >> 1;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}
template <class T, class F>
T bin_search(T ok, T ng, const F &f, int loop) {
	for(int i = 0; i < loop; i++) {
		T mid = (ok + ng) / 2;
		(f(mid) ? ok : ng) = mid;
	}
	return ok;
}

// others
struct fast_io {
	fast_io() {
		ios::sync_with_stdio(false);
		cin.tie(nullptr);
		cout << fixed << setprecision(15);
	}
} fast_io_;
const int inf = 1e9;
const ll INF = 1e18;
#pragma endregion

void main_();

int main() {
	main_();
	return 0;
}
#line 6 "e.cpp"

map<string, pll> memo;
pll score(string s) {
	if(memo.count(s)) return memo[s];
	if(s.empty()) {
		return memo[s] = {0, 1};
	}
	pll mx = {-inf, 1}, mn = {inf, 1};
	bool has_b = 0, has_w = 0;
	REP(i, SZ(s)) {
		if(s[i] == 'B') {
			has_b = 1;
			auto c = s;
			c.resize(i);
			auto nx = score(c);
			if(mx.first * nx.second < mx.second * nx.first) mx = nx;
		} else {
			has_w = 1;
			auto c = s;
			c.resize(i);
			auto nx = score(c);
			if(mn.first * nx.second > mn.second * nx.first) mn = nx;
		}
	}
	if(!has_b) {
		mn.first -= mn.second;
		return mn;
	}
	if(!has_w) {
		mx.first += mx.second;
		return mx;
	}
	//1/4以上 1/2

	REP(j, 40) {
		ll lef = divup(mx.first * (1ll << j), mx.second);
		if(mx.first < 0) {
			lef = mx.first * (1ll << j) / mx.second;
		}
		if((mx.first * (1ll << j)) % mx.second == 0) lef++;
		ll rig = mn.first * (1ll << j) / mn.second;
		if(mn.first < 0 and mn.first * (1ll << j) % mn.second) rig--;
		if((mn.first * (1ll << j)) % mn.second == 0) rig--;
		if(lef > rig) continue;
		if(lef * rig <= 0) {
			return memo[s] = {0, 1};
		} else {
			if(abs(lef) <= abs(rig)) {
				return memo[s] = {lef, 1ll << j};
			} else {
				return memo[s] = {rig, 1ll << j};
			}
		}
	}
	return {0, 0};
}

void main_() {
	INT(n);
	VEC(string, s, n);
	V<ll> wei(n);
	REP(i, n) {
		auto p = score(s[i]);
		while(p.second < (1ll << 40)) {
			p.first <<= 1;
			p.second <<= 1;
		}
		wei[i] = p.first;
	}

	if(n <= 20) {
		int res = 0;
		REP(bit, 1 << n) {
			ll sum = 0, val = 0;
			REP(i, n) {
				if(bit >> i & 1) {
					sum += wei[i];
					val += SZ(s[i]);
				}
			}
			if(sum == 0) {
				chmax(res, val);
			}
		}
		print(res);
	} else {
		map<ll, int> mp;
		int res = 0;
		REP(bit, 1 << 20) {
			ll sum = 0, val = 0;
			REP(i, 20) {
				if(bit >> i & 1) {
					sum += wei[i];
					val += SZ(s[i]);
				}
			}
			chmax(mp[sum], val);
		}
		REP(bit, 1 << (n - 20)) {
			ll sum = 0, val = 0;
			REP(i, n - 20) {
				if(bit >> i & 1) {
					sum += wei[i - 20];
					val += SZ(s[i - 20]);
				}
			}
			if(mp.count(-sum)) {
				chmax(res, val + mp[-sum]);
			}
		}
		print(res);
	}
}
accuracy: 0.045454545454545456
time_ms: 330
memory_kb: 68936
final_rank: 19

code_snippet: #include <bits/stdc++.h>
using namespace std;
using ll = long long;
using uint = unsigned int;
using ull = unsigned long long;
#define rep(i,n) for(int i=0;i<int(n);i++)
#define rep1(i,n) for(int i=1;i<=int(n);i++)
#define per(i,n) for(int i=int(n)-1;i>=0;i--)
#define per1(i,n) for(int i=int(n);i>0;i--)
#define all(c) c.begin(),c.end()
#define si(x) int(x.size())
#define pb push_back
#define eb emplace_back
#define fs first
#define sc second
template<class T> using V = vector<T>;
template<class T> using VV = vector<vector<T>>;
template<class T,class U> bool chmax(T& x, U y){
	if(x<y){ x=y; return true; }
	return false;
}
template<class T,class U> bool chmin(T& x, U y){
	if(y<x){ x=y; return true; }
	return false;
}
template<class T> void mkuni(V<T>& v){sort(all(v));v.erase(unique(all(v)),v.end());}
template<class T> int lwb(const V<T>& v, const T& a){return lower_bound(all(v),a) - v.begin();}
template<class T>
V<T> Vec(size_t a) {
    return V<T>(a);
}
template<class T, class... Ts>
auto Vec(size_t a, Ts... ts) {
  return V<decltype(Vec<T>(ts...))>(a, Vec<T>(ts...));
}
template<class S,class T> ostream& operator<<(ostream& o,const pair<S,T> &p){
	return o<<"("<<p.fs<<","<<p.sc<<")";
}
template<class T> ostream& operator<<(ostream& o,const vector<T> &vc){
	o<<"{";
	for(const T& v:vc) o<<v<<",";
	o<<"}";
	return o;
}
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n-1); }

#ifdef LOCAL
#define show(x) cerr << "LINE" << __LINE__ << " : " << #x << " = " << (x) << endl
void dmpr(ostream& os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ~ ";
	dmpr(os,args...);
}
#define shows(...) cerr << "LINE" << __LINE__ << " : ";dmpr(cerr,##__VA_ARGS__)
#define dump(x) cerr << "LINE" << __LINE__ << " : " << #x << " = {";  \
	for(auto v: x) cerr << v << ","; cerr << "}" << endl;
#else
#define show(x) void(0)
#define dump(x) void(0)
#define shows(...) void(0)
#endif

template<class D> D divFloor(D a, D b){
	return a / b - (((a ^ b) < 0 && a % b != 0) ? 1 : 0);
}
template<class D> D divCeil(D a, D b) {
	return a / b + (((a ^ b) > 0 && a % b != 0) ? 1 : 0);
}

ll Hackenbush(string s){
	// B = + = Left , W = - = Right
	const int K = 40;	// return number * 2^K
	int N = si(s);
	if(N == 0) return 0;
	ll res = 0;
	bool pre = true;
	int j = 0;
	for(char c: s){
		if(pre && c != s[0]) pre = false;
		if(!pre) j++;
		if(c == 'B') res += 1LL<<(K-j);
		else res -= 1LL<<(K-j);
	}
	return res;
}

int main(){
	cin.tie(0);
	ios::sync_with_stdio(false);		//DON'T USE scanf/printf/puts !!
	cout << fixed << setprecision(20);

	int N; cin >> N;
	V<ll> f(N);
	V<int> num(N);
	rep(i,N){
		string s; cin >> s;
		f[i] = Hackenbush(s);
		num[i] = si(s);
	}
	map<ll,ll> mp;
	int L = N/2, R = N-L;
	rep(s,1<<L){
		ll sum = 0;
		int n = 0;
		rep(i,L) if(s&1<<i) sum += f[i], n += num[i];
		chmax(mp[sum],n);
	}
	int res = 0;
	rep(s,1<<R){
		ll sum = 0;
		int n = 0;
		rep(i,R) if(s&1<<i) sum += f[i+L], n += num[i+L];
		if(mp.count(-sum)) chmax(res,mp[-sum] + n);
	}
	cout << res << endl;
}
accuracy: 1
time_ms: 900
memory_kb: 68976
final_rank: 7

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;
 
 
#define SIZE 40
 
struct Info{
 
    Info(int arg_num,ll arg_sum_value){
        num = arg_num;
        sum_value = arg_sum_value;
    }
    bool operator<(const struct Info &arg) const{
 
        return sum_value < arg.sum_value;
    }
 
    int num;
    ll sum_value;
};
 
int N,first_N;
ll POW[SIZE],POW2[SIZE];
ll value[SIZE];
int table[8000005];
char buf[SIZE+1];
int num_box[SIZE];
 
 
//簡易化のため、要素数を2のべき乗にする関数
void init(int first_N){
    while(N < first_N)N *= 2;
}
 
void update(int loc,ll value){
    loc += N-1;
 
    table[loc] = value;
 
    if(N == 1)return;
 
    int parent = (loc-1)/2;
 
    while(true){
        table[parent] = max(table[2*parent+1],table[2*parent+2]);
 
        if(parent == 0)break;
        else{
            parent = (parent-1)/2;
        }
    }
}
 
 
//任意の区間の最大を求める関数
int query(int search_left,int search_right,int node_id,int node_left,int node_right){ //table[node_id]に、node_left～node_righの区間の最小値が記録されているということt
 
    //今回のノードが検索区間をカバーしていなければ、結果に関係ない値を返す
    if(search_right < node_left || search_left > node_right)return -BIG_NUM;
 
    //今回のノードの区間が、検索区間の部分区間である場合、今回のノードの値を返す
    if(search_left <= node_left && search_right >= node_right){
        return table[node_id];
    }
 
    //今回のノードの区間に、一部検索区間と重なっている区間がある場合→再帰的に子どもに尋ねる
    int left_max = query(search_left,search_right,2*node_id+1,node_left,(node_left+node_right)/2);
    int right_max = query(search_left,search_right,2*node_id+2,(node_left+node_right)/2+1,node_right);
 
    return max(left_max,right_max);
}
 
 
 
 
int main(){
 
    POW[39] = 1;
    for(int i = 38; i >= 0; i--){
 
        POW[i] = POW[i+1]*2;
    }
 
    int first_N;
    scanf("%d",&first_N);
 
    int length;
 
    for(int i = 0; i < first_N; i++){
 
        scanf("%s",buf);
 
        for(length = 0; buf[length] != '\0'; length++);
        num_box[i] = length; //箱の数
 
        //pileを数値化する(bottom→top方向)
        ll tmp = 0;
        ll count = 0;
 
        if(buf[0] == 'B'){
 
            while(count < length && buf[count] == 'B')count++;
            tmp = POW[0]*count;
 
        }else{
 
            while(count < length && buf[count] == 'W')count++;
            tmp = POW[0]*(-1)*count;
        }
 
        int rank = 1;
 
        for(int k = count; k < length; k++){
 
            if(buf[k] == 'B'){
 
                tmp += POW[rank];
 
            }else{
 
                tmp -= POW[rank];
            }
            rank++;
        }
        value[i] = tmp;
    }
 
    //半分全列挙
    POW2[0] = 1;
    for(int i = 1; i < SIZE; i++){
 
        POW2[i] = POW2[i-1]*2;
    }
 
    int first_max = (first_N-1)/2;
    int first_num = first_max+1,second_num = first_N-first_num;
 
    vector<Info> FIRST,SECOND;
 
    //前半
    for(int state = 0; state < POW2[first_num]; state++){
 
        int num = 0;
        ll sum_value = 0;
 
        for(int loop = 0; loop < first_num; loop++){
            if(state & (1 << loop)){
                num += num_box[loop];
                sum_value += value[loop];
            }
        }
 
        FIRST.push_back(Info(num,sum_value));
    }
    sort(FIRST.begin(),FIRST.end()); //昇順
 
    //後半
    for(int state = 0; state < POW2[second_num]; state++){
 
        int num = 0;
        ll sum_value = 0;
 
        for(int loop = 0; loop < second_num; loop++){
            if(state & (1 << loop)){
                num += num_box[first_num+loop];
                sum_value += value[first_num+loop];
            }
        }
 
        SECOND.push_back(Info(num,sum_value));
    }
    sort(SECOND.begin(),SECOND.end());
 
    N = 1;
    init(SECOND.size());
 
    for(int i = 0; i <= 2*N-2; i++)table[i] = -BIG_NUM;
    for(int i = 0; i < SECOND.size(); i++){
 
        update(i,SECOND[i].num);
    }
 
    int ans = 0;
    int L,R,mid;
    int left,right;
 
    for(int i = 0; i < FIRST.size(); i++){
 
        //FIRST[i].sum_value+SECOND[k].sum_value == 0となるkの範囲を求める
 
        L = 0,R = SECOND.size()-1,mid = (L+R)/2;
        left = BIG_NUM; //左端
 
        while(L <= R){
 
            if(FIRST[i].sum_value+SECOND[mid].sum_value == 0){
 
                left = mid;
                R = mid-1;
 
            }else if(FIRST[i].sum_value+SECOND[mid].sum_value < 0){
 
                L = mid+1;
 
            }else{ //FIRST[i].sum_value+SECOND[mid].sum_value > 0
 
                R = mid-1;
 
            }
            mid = (L+R)/2;
        }
        if(left == BIG_NUM)continue;
 
        L = 0,R = SECOND.size()-1,mid = (L+R)/2;
        right = -BIG_NUM; //右端
 
        while(L <= R){
 
            if(FIRST[i].sum_value+SECOND[mid].sum_value == 0){
 
                right = mid;
                L = mid+1;
 
            }else if(FIRST[i].sum_value+SECOND[mid].sum_value < 0){
 
                L = mid+1;
 
            }else{ //FIRST[i].sum_value+SECOND[mid].sum_value > 0
 
                R = mid-1;
            }
            mid = (L+R)/2;
        }
        if(right == -BIG_NUM)continue;
 
        ans = max(ans,FIRST[i].num+query(left,right,0,0,N-1));
    }
 
    printf("%d\n",ans);
 
    return 0;
}
accuracy: 1
time_ms: 440
memory_kb: 44040
final_rank: 2

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 40

struct Info{

	Info(int arg_num,ll arg_sum_value){
		num = arg_num;
		sum_value = arg_sum_value;
	}
	bool operator<(const struct Info &arg) const{

		return sum_value < arg.sum_value;
	}

	int num;
	ll sum_value;
};

int N,first_N;
ll POW[SIZE],POW2[SIZE];
ll value[SIZE];
int table[8000005];
char buf[SIZE+1];
int num_box[SIZE];


//簡易化のため、要素数を2のべき乗にする関数
void init(int first_N){
	while(N < first_N)N *= 2;
}

void update(int loc,ll value){
	loc += N-1;

	table[loc] = value;

	if(N == 1)return;

	int parent = (loc-1)/2;

	while(true){
		table[parent] = max(table[2*parent+1],table[2*parent+2]);

		if(parent == 0)break;
		else{
			parent = (parent-1)/2;
		}
	}
}


//任意の区間の最大を求める関数
int query(int search_left,int search_right,int node_id,int node_left,int node_right){ //table[node_id]に、node_left～node_righの区間の最小値が記録されているということt

	//今回のノードが検索区間をカバーしていなければ、結果に関係ない値を返す
	if(search_right < node_left || search_left > node_right)return -BIG_NUM;

	//今回のノードの区間が、検索区間の部分区間である場合、今回のノードの値を返す
	if(search_left <= node_left && search_right >= node_right){
		return table[node_id];
	}

	//今回のノードの区間に、一部検索区間と重なっている区間がある場合→再帰的に子どもに尋ねる
	int left_max = query(search_left,search_right,2*node_id+1,node_left,(node_left+node_right)/2);
	int right_max = query(search_left,search_right,2*node_id+2,(node_left+node_right)/2+1,node_right);

	return max(left_max,right_max);
}




int main(){

	POW[39] = 1;
	for(int i = 38; i >= 0; i--){

		POW[i] = POW[i+1]*2;
	}

	int first_N;
	scanf("%d",&first_N);

	int length;

	for(int i = 0; i < first_N; i++){

		scanf("%s",buf);

		for(length = 0; buf[length] != '\0'; length++);
		num_box[i] = length; //箱の数

		//pileを数値化する(bottom→top方向)
		ll tmp = 0;
		ll count = 0;

		if(buf[0] == 'B'){

			while(count < length && buf[count] == 'B')count++;
			tmp = POW[0]*count;

		}else{

			while(count < length && buf[count] == 'W')count++;
			tmp = POW[0]*(-1)*count;
		}

		int rank = 1;

		for(int k = count; k < length; k++){

			if(buf[k] == 'B'){

				tmp += POW[rank];

			}else{

				tmp -= POW[rank];
			}
			rank++;
		}
		value[i] = tmp;
	}

	//半分全列挙
	POW2[0] = 1;
	for(int i = 1; i < SIZE; i++){

		POW2[i] = POW2[i-1]*2;
	}

	int first_max = (first_N-1)/2;
	int first_num = first_max+1,second_num = first_N-first_num;

	vector<Info> FIRST,SECOND;

	//前半
	for(int state = 0; state < POW2[first_num]; state++){

		int num = 0;
		ll sum_value = 0;

		for(int loop = 0; loop < first_num; loop++){
			if(state & (1 << loop)){
				num += num_box[loop];
				sum_value += value[loop];
			}
		}

		FIRST.push_back(Info(num,sum_value));
	}
	sort(FIRST.begin(),FIRST.end()); //昇順

	//後半
	for(int state = 0; state < POW2[second_num]; state++){

		int num = 0;
		ll sum_value = 0;

		for(int loop = 0; loop < second_num; loop++){
			if(state & (1 << loop)){
				num += num_box[first_num+loop];
				sum_value += value[first_num+loop];
			}
		}

		SECOND.push_back(Info(num,sum_value));
	}
	sort(SECOND.begin(),SECOND.end());

	N = 1;
	init(SECOND.size());

	for(int i = 0; i <= 2*N-2; i++)table[i] = -BIG_NUM;
	for(int i = 0; i < SECOND.size(); i++){

		update(i,SECOND[i].num);
	}

	int ans = 0;
	int L,R,mid;
	int left,right;

	for(int i = 0; i < FIRST.size(); i++){

		//FIRST[i].sum_value+SECOND[k].sum_value == 0となるkの範囲を求める

		L = 0,R = SECOND.size()-1,mid = (L+R)/2;
		left = BIG_NUM; //左端

		while(L <= R){

			if(FIRST[i].sum_value+SECOND[mid].sum_value == 0){

				left = mid;
				R = mid-1;

			}else if(FIRST[i].sum_value+SECOND[mid].sum_value < 0){

				L = mid+1;

			}else{ //FIRST[i].sum_value+SECOND[mid].sum_value > 0

				R = mid-1;

			}
			mid = (L+R)/2;
		}
		if(left == BIG_NUM)continue;

		L = 0,R = SECOND.size()-1,mid = (L+R)/2;
		right = -BIG_NUM; //右端

		while(L <= R){

			if(FIRST[i].sum_value+SECOND[mid].sum_value == 0){

				right = mid;
				L = mid+1;

			}else if(FIRST[i].sum_value+SECOND[mid].sum_value < 0){

				L = mid+1;

			}else{ //FIRST[i].sum_value+SECOND[mid].sum_value > 0

				R = mid-1;
			}
			mid = (L+R)/2;
		}
		if(right == -BIG_NUM)continue;

		ans = max(ans,FIRST[i].num+query(left,right,0,0,N-1));
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 1
time_ms: 450
memory_kb: 44056
final_rank: 3

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 40

struct Info{

	Info(int arg_num,ll arg_sum_value){
		num = arg_num;
		sum_value = arg_sum_value;
	}
	bool operator<(const struct Info &arg) const{

		return sum_value < arg.sum_value;
	}

	int num;
	ll sum_value;
};

int N,first_N;
ll POW[SIZE],POW2[SIZE];
ll value[SIZE];
int table[8000005];
char buf[SIZE+1];
int num_box[SIZE];


//簡易化のため、要素数を2のべき乗にする関数
void init(int first_N){
	while(N < first_N)N *= 2;
}

void update(int loc,ll value){
	loc += N-1;

	table[loc] = value;

	if(N == 1)return;

	int parent = (loc-1)/2;

	while(true){
		table[parent] = max(table[2*parent+1],table[2*parent+2]);

		if(parent == 0)break;
		else{
			parent = (parent-1)/2;
		}
	}
}


//任意の区間の最大を求める関数
int query(int search_left,int search_right,int node_id,int node_left,int node_right){ //table[node_id]に、node_left～node_righの区間の最小値が記録されているということt

	//今回のノードが検索区間をカバーしていなければ、結果に関係ない値を返す
	if(search_right < node_left || search_left > node_right)return -BIG_NUM;

	//今回のノードの区間が、検索区間の部分区間である場合、今回のノードの値を返す
	if(search_left <= node_left && search_right >= node_right){
		return table[node_id];
	}

	//今回のノードの区間に、一部検索区間と重なっている区間がある場合→再帰的に子どもに尋ねる
	int left_max = query(search_left,search_right,2*node_id+1,node_left,(node_left+node_right)/2);
	int right_max = query(search_left,search_right,2*node_id+2,(node_left+node_right)/2+1,node_right);

	return max(left_max,right_max);
}




int main(){

	POW[39] = 1;
	for(int i = 38; i >= 0; i--){

		POW[i] = POW[i+1]*2;
	}

	int first_N;
	scanf("%d",&first_N);

	int length;

	for(int i = 0; i < first_N; i++){

		scanf("%s",buf);

		for(length = 0; buf[length] != '\0'; length++);
		num_box[i] = length; //箱の数

		//pileを数値化する(bottom→top方向)
		ll tmp = 0;
		ll count = 0;

		if(buf[0] == 'B'){

			while(count < length && buf[count] == 'B')count++;
			tmp = POW[0]*count;

		}else{

			while(count < length && buf[count] == 'W')count++;
			tmp = POW[0]*(-1)*count;
		}

		int rank = 1;

		for(int k = count; k < length; k++){

			if(buf[k] == 'B'){

				tmp += POW[rank];

			}else{

				tmp -= POW[rank];
			}
			rank++;
		}
		value[i] = tmp;
	}

	//半分全列挙
	POW2[0] = 1;
	for(int i = 1; i < SIZE; i++){

		POW2[i] = POW2[i-1]*2;
	}

	int first_max = (first_N-1)/2;
	int first_num = first_max+1,second_num = first_N-first_num;

	vector<Info> FIRST,SECOND;

	//前半
	for(int state = 0; state < POW2[first_num]; state++){

		int num = 0;
		ll sum_value = 0;

		for(int loop = 0; loop < first_num; loop++){
			if(state & (1 << loop)){
				num += num_box[loop];
				sum_value += value[loop];
			}
		}

		FIRST.push_back(Info(num,sum_value));
	}
	sort(FIRST.begin(),FIRST.end()); //昇順

	//後半
	for(int state = 0; state < POW2[second_num]; state++){

		int num = 0;
		ll sum_value = 0;

		for(int loop = 0; loop < second_num; loop++){
			if(state & (1 << loop)){
				num += num_box[first_num+loop];
				sum_value += value[first_num+loop];
			}
		}

		SECOND.push_back(Info(num,sum_value));
	}
	sort(SECOND.begin(),SECOND.end());

	N = 1;
	init(first_N);

	for(int i = 0; i <= 2*N-2; i++)table[i] = -BIG_NUM;
	for(int i = 0; i < SECOND.size(); i++){

		update(i,SECOND[i].num);
	}

	int ans = 0;
	int L,R,mid;
	int left,right;

	for(int i = 0; i < FIRST.size(); i++){

		//FIRST[i].sum_value+SECOND[k].sum_value == 0となるkの範囲を求める

		L = 0,R = SECOND.size()-1,mid = (L+R)/2;
		left = BIG_NUM; //左端

		while(L <= R){

			if(FIRST[i].sum_value+SECOND[mid].sum_value == 0){

				left = mid;
				R = mid-1;

			}else if(FIRST[i].sum_value+SECOND[mid].sum_value < 0){

				L = mid+1;

			}else{ //FIRST[i].sum_value+SECOND[mid].sum_value > 0

				R = mid-1;

			}
			mid = (L+R)/2;
		}
		if(left == BIG_NUM)continue;

		L = 0,R = SECOND.size()-1,mid = (L+R)/2;
		right = -BIG_NUM; //右端

		while(L <= R){

			if(FIRST[i].sum_value+SECOND[mid].sum_value == 0){

				right = mid;
				L = mid+1;

			}else if(FIRST[i].sum_value+SECOND[mid].sum_value < 0){

				L = mid+1;

			}else{ //FIRST[i].sum_value+SECOND[mid].sum_value > 0

				R = mid-1;
			}
			mid = (L+R)/2;
		}
		if(right == -BIG_NUM)continue;

		ans = max(ans,FIRST[i].num+query(left,right,0,0,N-1));
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 0.045454545454545456
time_ms: 270
memory_kb: 43772
final_rank: 17

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 40

struct Info{

	Info(int arg_num,ll arg_sum_value){
		num = arg_num;
		sum_value = arg_sum_value;
	}
	bool operator<(const struct Info &arg) const{

		return sum_value < arg.sum_value;
	}

	int num;
	ll sum_value;
};

int N;
ll POW[SIZE],POW2[SIZE];
ll value[SIZE];
char buf[SIZE+1];
int num_box[SIZE];


int main(){

	POW[39] = 1;
	for(int i = 38; i >= 0; i--){

		POW[i] = POW[i+1]*2;
	}

	scanf("%d",&N);

	int length;

	for(int i = 0; i < N; i++){

		scanf("%s",buf);

		for(length = 0; buf[length] != '\0'; length++);
		num_box[i] = length; //箱の数

		//pileを数値化する(bottom→top方向)
		ll tmp = 0;
		ll count = 0;

		if(buf[0] == 'B'){

			while(count < length && buf[count] == 'B')count++;
			tmp = POW[0]*count;

		}else{

			while(count < length && buf[count] == 'W')count++;
			tmp = POW[0]*(-1)*count;
		}

		int rank = 1;

		for(int k = count; k < length; k++){

			if(buf[k] == 'B'){

				tmp += POW[rank];

			}else{

				tmp -= POW[rank];
			}
			rank++;
		}
		value[i] = tmp;
	}

	//半分全列挙
	POW2[0] = 1;
	for(int i = 1; i < SIZE; i++){

		POW2[i] = POW2[i-1]*2;
	}

	int first_max = (N-1)/2;
	int first_num = first_max+1,second_num = N-first_num;

	vector<Info> FIRST,SECOND;

	//前半
	for(int state = 0; state < POW2[first_num]; state++){

		int num = 0;
		ll sum_value = 0;

		for(int loop = 0; loop < first_num; loop++){
			if(state & (1 << loop)){
				num += num_box[loop];
				sum_value += value[loop];
			}
		}

		FIRST.push_back(Info(num,sum_value));
	}
	sort(FIRST.begin(),FIRST.end());

	//後半
	for(int state = 0; state < POW2[second_num]; state++){

		int num = 0;
		ll sum_value = 0;

		for(int loop = 0; loop < second_num; loop++){
			if(state & (1 << loop)){
				num += num_box[first_num+loop];
				sum_value += value[first_num+loop];
			}
		}

		SECOND.push_back(Info(num,sum_value));
	}
	sort(SECOND.begin(),SECOND.end());
	reverse(SECOND.begin(),SECOND.end());

	int ans = 0;
	int L = 0;

	for(int i = 0; i < FIRST.size(); i++){

		if(FIRST[i].sum_value+SECOND[L].sum_value == 0){

			for(int k = L; k < SECOND.size() && FIRST[i].sum_value+SECOND[k].sum_value == 0; k++){

				ans = max(ans,FIRST[i].num+SECOND[k].num);
			}

		}else if(FIRST[i].sum_value+SECOND[L].sum_value > 0){ //FIRST[i]は非減少なので、Lを増やす

			while(L < SECOND.size() && FIRST[i].sum_value+SECOND[L].sum_value > 0)L++;

		}else{ //FIRST[i].sum_value+SECOND[R].sum_value < 0

			//Do nothing
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 0.13636363636363635
time_ms: 220
memory_kb: 43704
final_rank: 15

code_snippet: #include<bits/stdc++.h>
typedef long long int ll;
typedef unsigned long long int ull;
#define BIG_NUM 2000000000
#define HUGE_NUM 99999999999999999
#define MOD 1000000007
#define EPS 0.000000001
using namespace std;


#define SIZE 40

struct Info{

	Info(int arg_num,ll arg_sum_value){
		num = arg_num;
		sum_value = arg_sum_value;
	}
	bool operator<(const struct Info &arg) const{

		return sum_value < arg.sum_value;
	}

	int num;
	ll sum_value;
};

int N;
ll POW[SIZE],POW2[SIZE];
ll value[SIZE];
char buf[SIZE+1];
int num_box[SIZE];


int main(){

	POW[39] = 1;
	for(int i = 38; i >= 0; i--){

		POW[i] = POW[i+1]*2;
	}

	scanf("%d",&N);

	int length;

	for(int i = 0; i < N; i++){

		scanf("%s",buf);

		for(length = 0; buf[length] != '\0'; length++);
		num_box[i] = length; //箱の数

		//pileを数値化する(bottom→top方向)
		ll tmp = 0;
		ll count = 0;

		if(buf[0] == 'B'){

			while(count < length && buf[count] == 'B')count++;
			tmp = POW[0]*count;

		}else{

			while(count < length && buf[count] == 'W')count++;
			tmp = POW[0]*(-1)*count;
		}

		int rank = 1;

		for(int k = count; k < length; k++){

			if(buf[k] == 'B'){

				tmp += POW[rank];

			}else{

				tmp -= POW[rank];
			}
			rank++;
		}
		value[i] = tmp;
	}

	//半分全列挙
	POW2[0] = 1;
	for(int i = 1; i < SIZE; i++){

		POW2[i] = POW2[i-1]*2;
	}

	int first_max = (N-1)/2;
	int first_num = first_max+1,second_num = N-first_num;

	vector<Info> FIRST,SECOND;

	//前半
	for(int state = 0; state < POW2[first_num]; state++){

		int num = 0;
		ll sum_value = 0;

		for(int loop = 0; loop < first_num; loop++){
			if(state & (1 << loop)){
				num += num_box[loop];
				sum_value += value[loop];
			}
		}

		FIRST.push_back(Info(num,sum_value));
	}
	sort(FIRST.begin(),FIRST.end());

	//後半
	for(int state = 0; state < POW2[second_num]; state++){

		int num = 0;
		ll sum_value = 0;

		for(int loop = 0; loop < second_num; loop++){
			if(state & (1 << loop)){
				num += num_box[first_num+loop];
				sum_value += value[first_num+loop];
			}
		}

		SECOND.push_back(Info(num,sum_value));
	}
	sort(SECOND.begin(),SECOND.end());
	reverse(SECOND.begin(),SECOND.end());

	int ans = 0;
	int R = SECOND.size()-1;

	for(int i = 0; i < FIRST.size(); i++){

		if(FIRST[i].sum_value+SECOND[R].sum_value == 0){

			for(int k = R; k >= 0 && FIRST[i].sum_value+SECOND[k].sum_value == 0; k--){

				ans = max(ans,FIRST[i].num+SECOND[k].num);
			}

		}else if(FIRST[i].sum_value+SECOND[R].sum_value > 0){ //FIRST[i]は非減少なので、Rを減らす

			while(R >= 0 && FIRST[i].sum_value+SECOND[R].sum_value > 0)R--;

		}else{ //FIRST[i].sum_value+SECOND[R].sum_value < 0

			//Do nothing
		}
	}

	printf("%d\n",ans);

	return 0;
}
accuracy: 0.045454545454545456
time_ms: 210
memory_kb: 43720
final_rank: 16

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

using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;
using LL = long long;
using VL = vector<LL>;
using VVL = vector<VL>;
using PLL = pair<LL, LL>;
using VS = vector<string>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)

#define FF first
#define SS second
template<class S, class T>
istream& operator>>(istream& is, pair<S,T>& p){
  return is >> p.FF >> p.SS;
}
template<class S, class T>
ostream& operator<<(ostream& os, const pair<S,T>& p){
  return os << p.FF << " " << p.SS;
}
template<class T>
void maxi(T& x, T y){
  if(x < y) x = y;
}
template<class T>
void mini(T& x, T y){
  if(x > y) x = y;
}


const double EPS = 1e-10;
const double PI  = acos(-1.0);
const LL MOD = 1e9+7;

//! represents x / (1<<y)
class Frac{
public:
  using LL = __int128;
  LL x, y;

  Frac(LL x = 0, LL y = 0) : x(x), y(y) { red(); }

  void red(){
	if(x == 0){
	  y = 0;
	  return;
	}

	while(y && x % 2 == 0){
	  x /= 2;
	  --y;
	}
  }

  Frac& operator += (const Frac &p){ LL l = max(y, p.y); x = (x<<(l-y)) + (p.x<<(l-p.y)); y = l; red(); return *this;}
  Frac operator + (const Frac &p) const{ Frac q = *this;return q += p;}
  Frac operator - () const { Frac q = *this; q.x *= -1; return q; }
  Frac& operator -= (const Frac &p){ Frac q = -p; *this += q; return *this;}
  Frac operator - (const Frac &p) const{ Frac q = *this; return q -= p;}
  Frac& operator *= (const Frac &a){ x *= a.x; y += a.y; red(); return *this;}
  Frac operator * (Frac a) const{ Frac q = *this; return q *= a;}

  bool operator < (const Frac &p) const{
	LL l = max(y, p.y);
	return (x << (l - y)) < (p.x << (l - p.y));
  }
  bool operator > (const Frac &p) const{
	return p < *this;
  }
  bool operator == (const Frac &p) const {
	return x == p.x && y == p.y;
  }
  bool operator <= (const Frac &p){
	return !(*this > p);
  }
  bool operator >= (const Frac &p){
	return !(*this < p);
  }
  LL floor() const { LL n = 1ll << y; return (x >= 0? x / n : (x-n) / n); }
  LL ceil() const { LL n = 1ll << y; return (x >= 0? (x+n-1) / n : x / n); }
  friend ostream& operator <<(ostream& os, const Frac& p);
};
ostream& operator <<(ostream& os, const Frac& p){
  return os ;//<< p.x << "/" << (1ll<<p.y);
}

Frac simplest(const Frac &l, const Frac &r){
  //cout<<"{ "<<l<<" | "<<r<<" } = ";
  for(LL k=0;;++k){
	Frac tmp = l * (1ll<<k);
	tmp.x++;
	tmp.red();
	Frac res(tmp.ceil(), k);
	if(l < res && res < r){
	  //cout<<res<<endl;
	  return res;
	}
  }
}

void calcNum(int N, string& s, vector<Frac>& xs){
  xs.resize(N+1);
  xs[0] = 0;
  Frac left, right;
  bool isLeftEmpty = true, isRightEmpty = true;
  FOR(i,1,N+1){
	if(s[i-1] == 'B'){
	  if(isLeftEmpty){
		isLeftEmpty = false;
		left = xs[i-1];
	  }
	  else
		left = max(left, xs[i-1]);
	  
	  if(isRightEmpty){
		xs[i] = left + 1;
	  }
	  else{
		xs[i] = simplest(left, right);
	  }
	}
	else{
	  if(isRightEmpty){
		isRightEmpty = false;
		right = xs[i-1];
	  }
	  else
		right = min(right, xs[i-1]);
	  
	  if(isLeftEmpty){
		xs[i] = right - 1;
	  }
	  else{
		xs[i] = simplest(left, right);
	  }
	}
  }
}

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

  int N, S = 0;
  cin >> N;
  vector<vector<Frac>> xs(N);
  REP(i,N){
	string s;
	cin >> s;
	S += SZ(s);
	calcNum(SZ(s), s, xs[i]);
  }

  /*
  REP(i,N){
	for(auto&p:xs[i])
	  cout<<p<<" , ";
	cout<<endl;
  }
  */

  int N2 = N / 2;
  vector<pair<Frac,int>> mem(1<<N2);
  REP(b,1<<N2){
	int sum = 0;
	Frac f;
	REP(i,N2)
	  if(b>>i&1)
		sum += SZ(xs[i])-1;
	  else
		f += xs[i].back();
	mem[b] = MP(f, sum);
  }
  SORT(mem);
  UNIQ(mem);

  int ans = S;
  REP(b,1<<(N-N2)){
	int sum = 0;
	Frac f;
	REP(i,N-N2)
	  if(b>>i&1)
		sum += SZ(xs[N2+i])-1;
	  else
		f += xs[N2+i].back();

	auto it = lower_bound(ALL(mem), MP(-f,0));
	if(it != end(mem) && it->FF == -f){
	  mini(ans, it->SS + sum);
	}
  }

  cout << S - ans << endl;

  return 0;
}
accuracy: 1
time_ms: 920
memory_kb: 52048
final_rank: 5

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

using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;
using LL = long long;
using VL = vector<LL>;
using VVL = vector<VL>;
using PLL = pair<LL, LL>;
using VS = vector<string>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)

#define FF first
#define SS second
template<class S, class T>
istream& operator>>(istream& is, pair<S,T>& p){
  return is >> p.FF >> p.SS;
}
template<class S, class T>
ostream& operator<<(ostream& os, const pair<S,T>& p){
  return os << p.FF << " " << p.SS;
}
template<class T>
void maxi(T& x, T y){
  if(x < y) x = y;
}
template<class T>
void mini(T& x, T y){
  if(x > y) x = y;
}


const double EPS = 1e-10;
const double PI  = acos(-1.0);
const LL MOD = 1e9+7;

//! represents x / (1<<y)
class Frac{
public:
  using LL = __int128;
  LL x, y;

  Frac(LL x = 0, LL y = 0) : x(x), y(y) { red(); }

  void red(){
	if(x == 0){
	  y = 0;
	  return;
	}

	while(y && x % 2 == 0){
	  x /= 2;
	  --y;
	}
  }

  Frac& operator += (const Frac &p){ LL l = max(y, p.y); x = (x<<(l-y)) + (p.x<<(l-p.y)); y = l; red(); return *this;}
  Frac operator + (const Frac &p) const{ Frac q = *this;return q += p;}
  Frac operator - () const { Frac q = *this; q.x *= -1; return q; }
  Frac& operator -= (const Frac &p){ Frac q = -p; *this += q; return *this;}
  Frac operator - (const Frac &p) const{ Frac q = *this; return q -= p;}
  Frac& operator *= (const Frac &a){ x *= a.x; y += a.y; red(); return *this;}
  Frac operator * (Frac a) const{ Frac q = *this; return q *= a;}

  bool operator < (const Frac &p) const{
	LL l = max(y, p.y);
	return (x << (l - y)) < (p.x << (l - p.y));
  }
  bool operator > (const Frac &p) const{
	return p < *this;
  }
  bool operator == (const Frac &p) const {
	return x == p.x && y == p.y;
  }
  bool operator <= (const Frac &p){
	return !(*this > p);
  }
  bool operator >= (const Frac &p){
	return !(*this < p);
  }
  LL floor() const { LL n = 1ll << y; return (x >= 0? x / n : (x-n) / n); }
  LL ceil() const { LL n = 1ll << y; return (x >= 0? (x+n-1) / n : x / n); }
  friend ostream& operator <<(ostream& os, const Frac& p);
};
ostream& operator <<(ostream& os, const Frac& p){
  return os ;//<< p.x << "/" << (1ll<<p.y);
}

Frac simplest(const Frac &l, const Frac &r){
  //cout<<"{ "<<l<<" | "<<r<<" } = ";
  for(LL k=0;;++k){
	Frac tmp = l * (1ll<<k);
	tmp.x++;
	tmp.red();
	Frac res(tmp.ceil(), k);
	if(l < res && res < r){
	  //cout<<res<<endl;
	  return res;
	}
  }
}

void calcNum(int N, string& s, vector<Frac>& xs){
  xs.resize(N+1);
  xs[0] = 0;
  Frac left, right;
  bool isLeftEmpty = true, isRightEmpty = true;
  FOR(i,1,N+1){
	if(s[i-1] == 'B'){
	  if(isLeftEmpty){
		isLeftEmpty = false;
		left = xs[i-1];
	  }
	  else
		left = max(left, xs[i-1]);
	  
	  if(isRightEmpty){
		xs[i] = left + 1;
	  }
	  else{
		xs[i] = simplest(left, right);
	  }
	}
	else{
	  if(isRightEmpty){
		isRightEmpty = false;
		right = xs[i-1];
	  }
	  else
		right = min(right, xs[i-1]);
	  
	  if(isLeftEmpty){
		xs[i] = right - 1;
	  }
	  else{
		xs[i] = simplest(left, right);
	  }
	}
  }
}

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

  int N, S = 0;
  cin >> N;
  vector<vector<Frac>> xs(N);
  REP(i,N){
	string s;
	cin >> s;
	S += SZ(s);
	calcNum(SZ(s), s, xs[i]);
  }

  /*
  REP(i,N){
	for(auto&p:xs[i])
	  cout<<p<<" , ";
	cout<<endl;
  }
  */

  int N2 = N / 2;
  map<Frac,int> mem;
  REP(b,1<<N2){
	int sum = 0;
	Frac f;
	REP(i,N2)
	  if(b>>i&1)
		sum += SZ(xs[i])-1;
	  else
		f += xs[i].back();
	if(!mem.count(f))
	  mem[f] = sum;
	else
	  mini(mem[f], sum);
  }

  int ans = S;
  REP(b,1<<(N-N2)){
	int sum = 0;
	Frac f;
	REP(i,N-N2)
	  if(b>>i&1)
		sum += SZ(xs[N2+i])-1;
	  else
		f += xs[N2+i].back();
	
	if(mem.count(-f))
	  mini(ans, mem[-f] + sum);
  }

  cout << S - ans << endl;

  return 0;
}
accuracy: 1
time_ms: 1670
memory_kb: 101548
final_rank: 12

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

using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;
using LL = long long;
using VL = vector<LL>;
using VVL = vector<VL>;
using PLL = pair<LL, LL>;
using VS = vector<string>;

#define ALL(a)  begin((a)),end((a))
#define RALL(a) (a).rbegin(), (a).rend()
#define PB push_back
#define EB emplace_back
#define MP make_pair
#define SZ(a) int((a).size())
#define SORT(c) sort(ALL((c)))
#define RSORT(c) sort(RALL((c)))
#define UNIQ(c) (c).erase(unique(ALL((c))), end((c)))

#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define REP(i,n)  FOR(i,0,n)

#define FF first
#define SS second
template<class S, class T>
istream& operator>>(istream& is, pair<S,T>& p){
  return is >> p.FF >> p.SS;
}
template<class S, class T>
ostream& operator<<(ostream& os, const pair<S,T>& p){
  return os << p.FF << " " << p.SS;
}
template<class T>
void maxi(T& x, T y){
  if(x < y) x = y;
}
template<class T>
void mini(T& x, T y){
  if(x > y) x = y;
}


const double EPS = 1e-10;
const double PI  = acos(-1.0);
const LL MOD = 1e9+7;

class Frac{
public:
  using LL = long long;
  LL x, y;

  Frac(LL x = 0, LL y = 1) : x(x), y(y) { red(); }

  LL gcd(LL x, LL y){
	if(y == 0) return x;
	return gcd(y, x%y);
  }
  
  void red(){
	if(x == 0){
	  y = 1;
	  return;
	}
	if(y < 0){
	  x *= -1;
	  y *= -1;
	}
	
	LL g = gcd(abs(x), y);
	x /= g;
	y /= g;
  }

  Frac& operator += (const Frac &p){ x = x * p.y + y * p.x; y *= p.y; red(); return *this;}
  Frac operator + (const Frac &p) const{ Frac q = *this;return q += p;}
  Frac operator - () const { Frac q = *this; q.x *= -1; return q; }
  Frac& operator -= (const Frac &p){ Frac q = -p; *this += q; return *this;}
  Frac operator - (const Frac &p) const{ Frac q = *this; return q -= p;}
  Frac& operator *= (const Frac &a){ x *= a.x; y *= a.y; red(); return *this;}
  Frac operator * (Frac a) const{ Frac q = *this; return q *= a;}
  Frac& operator /= (const Frac &a){ x *= a.y; y *= a.x; red(); return *this;}
  Frac operator / (Frac a) const{ Frac q = *this; return q /= a;}

  bool operator < (const Frac &p) const{
	return x * p.y < y * p.x;
  }
  bool operator > (const Frac &p) const{
	return p < *this;
  }
  bool operator == (const Frac &p) const {
	return x == p.x && y == p.y;
  }
  bool operator <= (const Frac &p){
	return !(*this > p);
  }
  bool operator >= (const Frac &p){
	return !(*this < p);
  }
  LL floor() const { return (x >= 0? x / y : (x-y) / y); }
  LL ceil() const { return (x >= 0? (x+y-1) / y : x / y); }
  double getR() const { return x * 1. / y; }
  friend ostream& operator <<(ostream& os, const Frac& p);
};
Frac abs(const Frac& q){ return Frac(abs(q.x), q.y); }
ostream& operator <<(ostream& os, const Frac& p){
  return os << p.x << "/" << p.y;
}

Frac simplest(const Frac &l, const Frac &r){
  //cout<<"{ "<<l<<" | "<<r<<" } = ";
  for(LL k=0;;++k){
	Frac tmp = l * (1ll<<k);
	tmp.x++;
	tmp.red();
	Frac res(tmp.ceil(), 1ll<<k);
	if(l < res && res < r){
	  //cout<<res<<endl;
	  return res;
	}
  }
}

void calcNum(int N, string& s, vector<Frac>& xs){
  xs.resize(N+1);
  xs[0] = 0;
  Frac left, right;
  bool isLeftEmpty = true, isRightEmpty = true;
  FOR(i,1,N+1){
	if(s[i-1] == 'B'){
	  if(isLeftEmpty){
		isLeftEmpty = false;
		left = xs[i-1];
	  }
	  else
		left = max(left, xs[i-1]);
	  
	  if(isRightEmpty){
		xs[i] = left + 1;
	  }
	  else{
		xs[i] = simplest(left, right);
	  }
	}
	else{
	  if(isRightEmpty){
		isRightEmpty = false;
		right = xs[i-1];
	  }
	  else
		right = min(right, xs[i-1]);
	  
	  if(isLeftEmpty){
		xs[i] = right - 1;
	  }
	  else{
		xs[i] = simplest(left, right);
	  }
	}
  }
}

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

  int N, S = 0;
  cin >> N;
  vector<vector<Frac>> xs(N);
  REP(i,N){
	string s;
	cin >> s;
	S += SZ(s);
	calcNum(SZ(s), s, xs[i]);
  }

  /*
  REP(i,N){
	for(auto&p:xs[i])
	  cout<<p<<" , ";
	cout<<endl;
  }
  */

  int N2 = N / 2;
  map<Frac,int> mem;
  REP(b,1<<N2){
	int sum = 0;
	Frac f;
	REP(i,N2)
	  if(b>>i&1)
		sum += SZ(xs[i])-1;
	  else
		f += xs[i].back();
	if(!mem.count(f))
	  mem[f] = sum;
	else
	  mini(mem[f], sum);
  }

  int ans = S;
  REP(b,1<<(N-N2)){
	int sum = 0;
	Frac f;
	REP(i,N-N2)
	  if(b>>i&1)
		sum += SZ(xs[N2+i])-1;
	  else
		f += xs[N2+i].back();
	
	if(mem.count(-f))
	  mini(ans, mem[-f] + sum);
  }

  cout << S - ans << endl;

  return 0;
}
accuracy: 0.045454545454545456
time_ms: 1960
memory_kb: 68652
final_rank: 20