DPする。
dp [ i ] [ j ] = i から j までの間で作れるパターン数
意外と難しかった。
- vector<int> C;
- int N;
- const int M = 50 + 1;
- lli memo[M][M];
- const lli mod = 100000007;
- // [... a, b, ...]
- bool next(int a, int b)
- {
- return (a + 1) % N == b;
- }
- lli rec(int i, int j)
- {
- if (next(i, j)) return 1;
- lli &ret = memo[i][j];
- if (ret != -1) return ret;
- lli sum = rec(i + 1, j);
- for (int k = i + 2; k < j; ++k) {
- if (C[i] != C[k]) {
- sum += rec(i, k) * rec(k, j) / 2LL;
- sum %= 2LL * mod;
- }
- }
- if (C[i] != C[j] && !next(i, j) && !next(j, i)) {
- sum *= 2LL;
- sum %= 2LL * mod;
- }
- return ret = sum;
- }
- class PolygonColors {
- public:
- int getWays(int N_, vector <int> C_)
- {
- N = N_;
- C = C_;
- for (int i = 0; i < (int)N; ++i) {
- int j = (i + 1) % C.size();
- if (C[i] == C[j]) return 0;
- }
- fill(&memo[0][0], &memo[M - 1][M], -1);
- return rec(0, N - 1) % mod;
- }
- };