250
マンハッタン距離が dist 以下の点同士をまとめておく。
"選ぶ" or "選ばない"の2択で偶数になる場合を数え上げる。
DP[どこまで見た][総和の遇奇]=パターン
マンハッタン距離が dist 以下の点同士をまとめておく。
"選ぶ" or "選ばない"の2択で偶数になる場合を数え上げる。
DP[どこまで見た][総和の遇奇]=パターン
class GooseInZooDivOne { public: int count(vector <string> g, int dist) { const int H = g.size(); const int W = g[0].size(); vector< pair<int, int> > v; for (int i = 0; i < H; ++i) { for (int j = 0; j < W; ++j) { if (g[i][j] == 'v') { v.push_back(make_pair(i, j)); } } } if (v.size() == 0) return 0; const int N = v.size(); UnionFind uf(N); for (int i = 0; i < N; ++i) { uf.make(i); } for (int i = 0; i < N; ++i) { for (int j = i + 1; j < N; ++j) { int a = v[i].first - v[j].first; int b = v[i].second - v[j].second; if (abs(a) + abs(b) <= dist) { uf.unite(i, j); } } } for (int i = 0; i < N; ++i) { for (int j = 0; j < N; ++j) { uf.isSameSet(i, j); uf.find(i); } } map<int, int> m; for (int i = 0; i < N; ++i) { ++m[uf.find(i, false)]; } vector<int> u; each (i, m) { u.push_back(i->second); } lli dp[2][2]; dp[0][0] = dp[0][1] = dp[1][0] = dp[1][1] = 0; dp[0][0] = 1; int curr = 0; int next = 0; for (int j = 0; j < u.size(); ++j) { curr = j % 2; next = (curr + 1) % 2; dp[next][0] = dp[next][1] = 0; for (int k = 0; k <= 1; ++k) { dp[next][k] += dp[curr][k]; dp[next][k] %= mod; dp[next][(k + u[j]) % 2] += dp[curr][k]; dp[next][k] %= mod; } } return (dp[next][0] + mod - 1) % mod; } }