🕌
HHKB2020-E Lamps (確率ベースで考える方法)
問題
解説(ネタバレ注意!)
公式解説と少し違ったアプローチをしたので、記事にしておきます。
全体の
-
と同じマス(i, j) -
と同じ行のマス(i, j) -
と同じ列のマス(i, j)
に照明が置かれたとき、そのマスは照らされます。
各マスが照らされるのは、全体の
ここで、逆に照らされない時の確率を求めます、その値を
つまり、上記
となります。
実装例
union-find
でサボりました。
void solve(){
int h, w;
cin >> h >> w;
vector<string> s(h);
rep(i, h)cin >> s[i];
union_find uf_row(h * w), uf_col(h * w);
rep(i, h)rep(j, w - 1){
if(s[i][j] == '.' && s[i][j + 1] == '.')uf_col.unite(i * w + j, i * w + j + 1);
}
rep(i, h - 1)rep(j, w){
if(s[i][j] == '.' && s[i + 1][j] == '.')uf_row.unite(i * w + j, (i + 1) * w + j);
}
int k = 0;
rep(i, h)rep(j, w)if(s[i][j] == '.')k++;
mint pow = 1;
rep(_, k)pow *= 2;
vector<mint> p2(k + 1);
p2[0] = 1;
rep(i, k)p2[i + 1] = p2[i] / mint(2);
mint ans = 0;
rep(i, h)rep(j, w){
if(s[i][j] == '#')continue;
ans += (mint(1) - p2[uf_col.get_size(i * w + j) + uf_row.get_size(i * w + j) - 1]) * pow;
}
cout << ans << endl;
}
Discussion