[ARC132] C - Almost Sorted
[Q] https://atcoder.jp/contests/arc132/submissions/28201565
1. d=5が、とても厳しい制限。けど何に使うんだろう?
2. indexごとに状態遷移するからDPっぽい。どの数値を使ったか保持しておきたいと思う。
3. DP[510][2^500] は無理。
4. d=5だとして、a-5 ~ a+5の11通りの数字しかとりえないのがわかる。DP[510][2^11]で求められそう。
5. indexを動かすごとに、右に1bitずらせばよさそう。
Q.
D=2
-1 -1 -1 -1
とする。
0. bit管理
D=2なので、どの値も5個の範囲をとる。
DP[5][2^5] で管理。
1. 初期条件
DP[0][00011] = 1をとる。
入力値を0-indexedとみなして、
bit:0 0 0 1 1
2 1 0-1-2 が入るかどうかを表している。
-1, -2 は入りえないので、すでに使用済み扱い。1を立てている。
2. DP遷移
・-1(0index)の処理
まず、現状から1つbitを追加できる場合に遷移する。
DP[0][00011] = 1 -> DP[0][00111] = 1 // 0を採用する
-> DP[0][01011] = 1 // 1を採用する
-> DP[0][10011] = 1 // 2を採用する
210-1-2 // この5bitが管理しているのは2 ~ -2
次に、bitを1つ右にずらして、確定させる
DP[0][00111] = 1 -> DP[1][00011] = 1
DP[0][01011] = 1 -> DP[1][00101] = 1
DP[0][10011] = 1 -> DP[1][01001] = 1
3210-1 // この5bitが管理しているのは3 ~ -1
3. 終了条件。
DP[4][00011] = 14 が回答になる。
// 初期条件
DP[0][00011]:1
// 新たにbitを1本追加して、右に1bitシフト
DP[1][00011]:1
DP[1][00101]:1
DP[1][01001]:1
// 新たにbitを1本追加して、右に1bitシフト
DP[2][00011]:2
DP[2][00101]:2
DP[2][00110]:2
DP[2][01001]:1
DP[2][01010]:1
DP[2][01100]:1
// 新たにbitを1本追加して、右に1bitシフト
DP[3][00011]:6
DP[3][00101]:4
DP[3][00110]:4
DP[3][00111]:4
DP[3][01001]:2
DP[3][01010]:2
DP[3][01011]:2
DP[3][01100]:1
DP[3][01101]:1
DP[3][01110]:1
// 新たにbitを1本追加して、右に1bitシフト
DP[4][00011]:14 << ans
DP[4][00101]:10
DP[4][00110]:7
DP[4][00111]:15
DP[4][01001]:6
DP[4][01010]:4
DP[4][01011]:8
DP[4][01100]:2
DP[4][01101]:4
DP[4][01110]:2
DP[4][01111]:1
14
実装
ll N, D;
mint DP[510][1 << 11];
ll A[510];
int main() {
cincout();
cin >> N >> D;
rep(i, N) {
cin >> A[i];
--A[i];
}
DP[0][(1 << D) - 1] = 1; // 00011
rep(i, N) {
ll a = A[i];
if (a != -2) { // 定数が来て、それが条件を外れてるならダメ
if (a > i + D || a < i - D) {
cout << 0 << endl;
return 0;
}
}
rep(j, 1 << (D * 2 + 1)) {
if (DP[i][j] == 0) continue;
if (a != -2) {
ll shift = a - i + D;
if (is_pop(j, shift)) continue;
ll nj = j | (1 << shift);
nj >>= 1;
DP[i + 1][nj] += DP[i][j];
}
// 00011->00111にしたい
else {
rep(x, D * 2 + 1) {
if (is_pop(j, x)) continue;
ll nj = j | (1 << x);
nj >>= 1;
DP[i + 1][nj] += DP[i][j];
}
}
}
}
cout << DP[N][(1 << D) - 1] << endl;
}
この記事が気に入ったらサポートをしてみませんか?