memo[最初に選んだヤツ][最後に選んだヤツ][残りのA][残りのB][残りのC]
const int N = 50 + 1; const int A = 0, B = 1, C = 2, D = 3; const int LAST = 4, FIRST = 4; lli memo[FIRST][LAST][N][N][N]; const lli mod = 1000000007; lli rec(int first, int last, int a, int b, int c) { lli &ret = memo[first][last][a][b][c]; if (ret != -1) return ret; if (a == 0 && b == 0 && c == 0) { return last != first; } lli sum = 0; if (first == D) { if (a) sum = (sum + rec(A, A, a - 1, b, c)) % mod; if (b) sum = (sum + rec(B, B, a, b - 1, c)) % mod; if (c) sum = (sum + rec(C, C, a, b, c - 1)) % mod; } else { if (last == A) { if (b) sum = (sum + rec(first, B, a, b - 1, c)) % mod; if (c) sum = (sum + rec(first, C, a, b, c - 1)) % mod; } if (last == B) { if (a) sum = (sum + rec(first, A, a - 1, b, c)) % mod; if (c) sum = (sum + rec(first, C, a, b, c - 1)) % mod; } if (last == C) { if (a) sum = (sum + rec(first, A, a - 1, b, c)) % mod; if (b) sum = (sum + rec(first, B, a, b - 1, c)) % mod; } } return ret = sum; } class ColorfulCupcakesDivTwo { public: int countArrangements(string C) { int a = count(C.begin(), C.end(), 'A'); int b = count(C.begin(), C.end(), 'B'); int c = count(C.begin(), C.end(), 'C'); fill(&memo[0][0][0][0][0], &memo[FIRST][0][0][0][0], -1); return rec(D, D, a, b, c) % mod; } };