题解 AT_abc216_h【[ABC216H] Random Robots】
前置知识:LGV,感谢 THU POG。
看到机器人不碰撞的条件,可以想到这题需要 LGV 引理。由于这道题中起点固定,但是终点不固定,于是考虑枚举终点。
我们考虑确定了终点序列 \(y_1,y_2,\cdots,y_K\),由于路径不能相交的限制,所以起点和终点的匹配是唯一的,即路径为 \((x_1,y_1),(x_2,y_2),\cdots,(x_k,y_k)\),(\((x,y)\) 表示起点为 \(x\) 终点为 \(y\) 的一条路径。
考虑套上 LGV 引理,可得,路径的方案数为:
\[\begin{vmatrix}e(x_1,y_1)&e(x_1,y_2)&\cdots&e(x_1,y_K)\\e(x_2,y_1)&e(x_2,y_2)&\cdots&e(x_2,y_K)\\\vdots&\ddots&\vdots\\e(x_k,y_1)&e(x_k,y_2)&\cdots&e(x_k,y_k)\end{vmatrix}
\]
\(e(x,y)\) 表示 \(x\) 到 \(y\) 的方案数。在本题中,\(e(x,y)=\binom{n}{y - x}\)。
考虑拆行列式的贡献,考虑设 \(f(S, mx)\) 表示确定起点(\(x'\))的集合为 \(S\),且对应 \(y_{|S|} \le mx\) 的行列式值, 即:
\[\begin{vmatrix}e(x'_1,y_1)&e(x'_1,y_2)&\cdots&e(x'_1,y_{|S|})\\e(x'_2,y_1)&e(x'_2,y_2)&\cdots&e(x'_2,y_{|S|})\\\vdots&\ddots&\vdots\\e(x'_{|S|},y_1)&e(x'_{|S|},y_2)&\cdots&e(x'_{|S|},y_{|S|})\end{vmatrix}
\]
转移:
-
\(y_{|S|} < mx\),\(f(S,mx - 1) \to f(s, mx)\);
-
\(y_{|S|} = mx\),这个时候考虑最后一列的贡献:
-
我们考虑行列式的定义:\(|A|=\sum\limits_{p_1,p_2,\cdots,p_n} (-1)^{\sigma(p_1,p_2,\cdots,p_n)}A_{i,p_i}\)。
-
我们考虑枚举 \(p_i={|S|}\),那么贡献就是 \((-1)^{|S|-i}e(x'_i,y_k)\),乘上前面 \(p_1,p_2,\cdots,p_{|S|-1}\) 的答案和,就是 \(f(S \backslash x'_{i},mx-1)\to f(s, mx)\)。
-
求出方案数之后,概率就是再乘上 \(2^{-nk}\)。
代码:
#include <bits/stdc++.h>
#define SZ(x) (int) x.size() - 1
#define all(x) x.begin(), x.end()
#define ms(x, y) memset(x, y, sizeof x)
#define F(i, x, y) for (int i = (x); i <= (y); i++)
#define DF(i, x, y) for (int i = (x); i >= (y); i--)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template <typename T> void chkmax(T &x, T y) { x = max(x, y); }
template <typename T> void chkmin(T &x, T y) { x = min(x, y); }
template <typename T> void read(T &x) {
x = 0; int f = 1; char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = x * 10 + c - '0';
x *= f;
}
const int K = 11, N = 1010, MOD = 998244353;
template <typename T1, typename T2> void add(T1 &x, T2 y) { x = (x + y) % MOD; }
int n, k, x[K], f[N * 2][1 << 10], C[N][N];
void init(int n) {
F(i, 0, n) {
C[i][0] = 1;
F(j, 1, i) C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % MOD;
}
}
int CC(int n, int m) {
return m < 0 || n < m ? 0 : C[n][m];
}
int e(int x, int y) {
return CC(k, y - x);
}
int power(int x, int y = MOD - 2) {
int ans = 1;
for (; y; x = (ll) x * x % MOD, y >>= 1)
if (y & 1) ans = (ll) ans * x % MOD;
return ans;
}
signed main() {
read(n); read(k);
init(k);
F(i, 1, n) read(x[i]), x[i]++;
int full = (1 << n) - 1;
f[0][0] = 1;
F(i, 1, x[n] + k) {
F(j, 0, full) {
f[i][j] = f[i - 1][j];
int sz = __builtin_popcount(j), s = 0;
F(k, 1, n) {
int t = (1 << (k - 1));
if (j & t) {
s++;
int pie = ((sz + s) & 1) ? MOD - 1 : 1;
add(f[i][j], (ll) f[i - 1][j ^ t] * pie % MOD * e(x[k], i));
}
}
}
} cout <<(ll) f[x[n] + k][full] * power(power(2), n * k) % MOD;
return 0;
}

浙公网安备 33010602011771号