題解: Minimum OR is X
阿新 • • 發佈:2021-11-09
Problem Statement
給定三個正整數 \(N, M, K\) 和非負整數 \(X\) 。
求出有多少個滿足以下條件的長為 \(N\) 的非負整數列 \(A = (A_1, A_2, \cdots, A_N)\) 個數,答案對 \(\rm 998244353\) 取模:
- \(0\le A_i \le 2 ^ M - 1\ (1\le i\le N)\)
- 數列 \(A\) 中任意選擇 \(K\) 個位置 \(i_1, i_2, \cdots, i_K \ (i_a\neq i_b)\) ,滿足 \(\min\{A_{i_1}\oplus A_{i_2}\oplus\cdots\oplus A_{i_K}\} = X\)
其中 \(\oplus\) 運算代表 C++
中的按位或運算。
Constraints
\(1\le N, M\le 200\) ,\(1\le K \le N\) ,\(0\le X\le 2 ^ M - 1\) ,\(X\) 以二進位制字串的形式給出。
solution
從高到低按位貪心,發現對於每一層,如果有 \(\ge K\) 個 0
那麼這一位必定為 0
,否則為 1
。
那麼貪心取 0
的時候,那麼所有該層為 1
的元素都不能取了,所以在考慮下面層的時候,這些元素就不能考慮了。
對於這個過程設計一個 DP
,設 \(f(i, j)\) 表示從高到低到第 \(i\) 位,還有 \(j\)
對於貪心的方案,設計兩種轉移:
- \(X\) 該位為
0
,設 \(k\) 為該層1
的個數。 -
- \(f(i, j) \leftarrow \displaystyle\sum_{k = 0} ^ {n - K} f(i + 1, j + k) \times \dbinom{j + k}{j} \times 2 ^ {k(i - 1)}\)
- \(X\) 該位為
1
,設 \(k\) 為該層0
的個數。 -
- \(f(i, j) \leftarrow f(i + 1, j) \times \displaystyle{\sum_{k = 0} ^ {K - 1}}\dbinom{j}{k}\)
- \(f(i, j) \leftarrow f(i + 1, j) \times \displaystyle{\sum_{k = 0} ^ {K - 1}}\dbinom{j}{k}\)
答案就是 \(\sum f(0, i)\) 。
Mint fac[N << 1], ifac[N << 1];
inline void table(int lim) {
fac[0] = Mint(1);
forn (i, 1, lim) fac[i] = fac[i - 1] * Mint(i);
ifac[lim] = q_pow(fac[lim]);
form (i, lim - 1, 0) ifac[i] = ifac[i + 1] * Mint(i + 1);
}
inline Mint C(int n, int r) {
if (n < 0 || r < 0 || n < r) return Mint(0);
return fac[n] * ifac[r] * ifac[n - r];
}
int n, m, K; char X[N]; Mint f[N][N];
inline void solve() {
Rdn(n, m, K); Rdn(X); table(max(n, m) << 1);
reverse(X, X + m);
f[m][n] = Mint(1);
form (i, m - 1, 0) forn (j, 0, n) {
if (X[i] == '0') {
if (j >= K) forn (k, 0, n - K) if (j + k <= n) {
f[i][j] += f[i + 1][j + k] * C(j + k, k) * q_pow(Mint(2), k * i);
}
} else {
forn (k, 0, K - 1) f[i][j] += f[i + 1][j] * C(j, k);
}
}
Mint res(0);
forn (i, 0, n) res += f[0][i];
Wtn(res.res, '\n');
}