题解 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} \]

转移:

  1. \(y_{|S|} < mx\)\(f(S,mx - 1) \to f(s, mx)\)

  2. \(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;
}
posted @ 2023-03-14 21:13  zhaohaikun  阅读(37)  评论(0)    收藏  举报