题解:P15612 [ICPC 2021 Jakarta R] Feeder Robot

不妨假设 \(A\leq B\)

设第 \(i\) 条边连接点 \(i\)\(i+1\),考虑把点覆盖次数转化为边覆盖次数。设 \(l_i\) 为向左走的覆盖边 \(i\) 的次数,\(r_i\) 为向右走覆盖边 \(i\) 的次数,则 \(S_i=[A=i]+l_i+r_{i-1}\),不难证明由 \(S_{1\sim n}\) 可以还原出 \((l_i,r_i)\)

设起点和终点分别为 \(A,B\),观察到对于 \(A\leq i<B\)\(r_i-l_i=1\),而对于 \(i<A\lor i\geq B\)\(l_i=r_i\)。将移动看作走有向边,则点 \(i\) 的入度为 \(r_{i-1}+l_i\),出度为 \(l_{i-1}+r_i\)。不难得出点 \(A\) 出度恰好比入度多 \(1\),点 \(B\) 出度恰好比入度多 \(1\),其他点出入度相等。于是存在 \(A\)\(B\) 的欧拉路径。这说明 \(S_{1\sim n}\) 与合法的 \((l_i,r_i)\) 构成双射。

考虑 \(w_i=l_i+r_i\),设机器人访问过的最左点为 \(L\),最右点为 \(R\),刻画 \(w_{1\sim n-1}\) 合法的条件:

  • 对于 \(L\leq i<A\lor B\leq i<R\)\(w_i\) 为正偶数。
  • 对于 \(A\leq i<B\)\(w_i\) 为正奇数。
  • 对于 \(i<L\lor i\geq R\)\(w_i=0\)
  • \(\sum_{i=1}^{n-1}w_i=m-1\)

对于 \(L\leq i<A\lor B\leq i<R\),设 \(w_i=2t_i+2\);对于 \(A\leq i<B\),设 \(w_i=2t_i+1\)。再设 \(d=B-A\)\(k=R-L\),由插板法容易得出,固定 \(d,k\) 后分配 \(w_i\) 的方案数为

\[\binom{(m-1-2k+d)/2+k-1}{k-1}=\binom{(m-1+d)/2-1}{k-1} \]

注意还需要满足 \(m-1\geq 2k-d\)\(m-1\equiv 2k-d \pmod{2}\)

\(c=R-A\),容易推出 \(c\) 的取值范围为 \([\max(k-A+1,d),\min(n-A,k)]\)

枚举 \(k,c\),则我们要计算

\[\sum_{\substack{\max(2k-m+1, lim)\leq d\leq c\\d\equiv 2k-m+1\pmod{2}}}\binom{(m-1+d)/2-1}{k-1} \]

这里 \(lim\) 的限制是为了方便另一侧的计数。当 \(A\leq B\)\(lim=0\);当 \(A>B\)\(lim=1\)

观察到对 \(d\bmod{2}\) 有限制会使得上指标连续,对于上指标求和,有结论

\[\sum_{i=l}^r\binom{a+i}{b}=\binom{a+r+1}{b+1}-\binom{a+l}{b+1} \]

证明不难,把 \(\dbinom{a+i}{b}\) 拆成 \(\dbinom{a+i+1}{b+1}-\dbinom{a+i}{b+1}\) 即可。

\(d\) 在限制条件内能取到的最小值为 \(d_{mn}\),最大值为 \(d_{mx}\),则原式可以化为

\[\binom{(m-1+d_{mx})/2}{k}-\binom{(m-1+d_{mn})/2-1}{k} \]

进一步把 \(c\) 搞掉,我们要快速计算

\[\sum_{c=c_l}^{c_r}\binom{(m-1+d_{mx})/2}{k}-\binom{(m-1+d_{mn})/2-1}{k} \]

只有 \(d_{mx}\) 的取值和 \(c\) 有关,因此第二个组合数可以直接拎出来算。

于是我们只需要算

\[\sum_{c=c_l}^{c_r}\binom{\lfloor(m-1+c)/2\rfloor}{k} \]

\(c\) 的奇偶性拆开来算,同奇偶的 \(c\) 再次用上指标求和计算即可。

时间复杂度 \(\mathcal{O}(n)\)

主要代码
int n, m, A;
mint fac[MAXN], ifac[MAXN];

void init(int n) {
	fac[0] = 1;
	for (int i = 1; i <= n; ++i) fac[i] = fac[i - 1] * i;
	ifac[n] = fac[n].inv();
	for (int i = n - 1; i >= 0; --i) ifac[i] = ifac[i + 1] * (i + 1);
}

mint C(int n, int m) {
	return n < 0 || m < 0 || n < m ? 0 : fac[n] * ifac[m] * ifac[n - m];
}

mint solve(int A, int lim) {
	mint res = 0;
	for (int k = 1; k <= n; ++k) {
		int d1 = max(lim, k * 2 - m + 1);
		if ((d1 & 1) == (m & 1)) ++d1;
		int L = max(d1, k - A + 1), R = min(n - A, k);
		if (L > R) continue;
		res -= C((m - 1 + d1 >> 1) - 1, k) * (R - L + 1);
		int L0 = L + (L & 1), L1 = L + (~L & 1), R0 = R - (R & 1), R1 = R - (~R & 1);
		res += C((m - 1 + R0 >> 1) + 1, k + 1) - C((m - 1 + L0 >> 1), k + 1) + C((m - 1 + R1 >> 1) + 1, k + 1) - C((m - 1 + L1 >> 1), k + 1);
	}
	return res;
}

int main() {
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	
	cin >> n >> m >> A;

	if (m == 1) {
		cout << "1";
		return 0;
	}

	init(n + m);
	cout << solve(A, 0) + solve(n + 1 - A, 1);
	return 0;
}
posted @ 2026-07-29 20:07  P2441M  阅读(3)  评论(0)    收藏  举报