Typical DP Contest M - 家
問題
H階建ての家がある。各階は全て同じ構造をしていて、r部屋からなり、
g[i][j] = 1のとき部屋iから部屋jへ行くことができる。
また、h階の部屋iからはh-1階の部屋iへ降りることができる。(登れない)
H階の部屋1から1階の部屋1まで、同じ部屋を2度通らないで行く場合の数をmod 10^9 + 7で求めよ。
制約条件
H≦10^9
r≦16
方針
一つの階で同じ部屋を通らずiからjまで行く場合の数は、
巡回セールスマン的なDPで、
dp[bit][i] := bitの部屋を通ってiにいるときの場合の数
をそれぞれの始点kからDPすれば求まる。
すると、1階をi, jまで降りるときの場合の数の行列Aができる。
2階のときはA^2……で、A^Hを繰り返し二乗法で求めればよい。
ソースコード
void calc(int s, vi &way){ memset(dp, 0, sizeof(dp)); dp[1 << s][s] = 1; rep(i, 1 << r) rep(j, r) if(dp[i][j]){ rep(k, r) if(!(i & 1 << k) && g[j][k]) (dp[i | 1 << k][k] += dp[i][j]) %= mod; } rep(i, 1 << r) rep(j, r) (way[j] += dp[i][j]) %= mod; } int main(){ cin >> h >> r; rep(i, r) rep(j, r) cin >> g[i][j]; way.resize(r); rep(i, r) way[i].resize(r), calc(i, way[i]); way = pw(way, h); cout << way[0][0] << endl; return 0; }