题解: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\) 的方案数为
注意还需要满足 \(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\),则我们要计算
这里 \(lim\) 的限制是为了方便另一侧的计数。当 \(A\leq B\) 时 \(lim=0\);当 \(A>B\) 时 \(lim=1\)。
观察到对 \(d\bmod{2}\) 有限制会使得上指标连续,对于上指标求和,有结论
证明不难,把 \(\dbinom{a+i}{b}\) 拆成 \(\dbinom{a+i+1}{b+1}-\dbinom{a+i}{b+1}\) 即可。
设 \(d\) 在限制条件内能取到的最小值为 \(d_{mn}\),最大值为 \(d_{mx}\),则原式可以化为
进一步把 \(c\) 搞掉,我们要快速计算
只有 \(d_{mx}\) 的取值和 \(c\) 有关,因此第二个组合数可以直接拎出来算。
于是我们只需要算
按 \(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;
}

浙公网安备 33010602011771号