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;
}
}