题解 CF1204E 【Natasha, Sasha and the Prefix Sums】
题意
求所有只有
解题思路
设
下一步我沿用了 P1641 字符串生成 里的经典套路。将
正如下图,是序列
而最大前缀和大于等于
如果起点和终点在直线同侧怎么办?强行把起点移到另一边去!不妨设置新的起点
接下来的转换将数形结合的精粹表现得淋漓尽致:我们找到路径与
想想看,这样的翻转是不是可以把老的路径中与
放个图稍加体会:
最后一步,
故
总结一下:
线性预处理阶乘及逆元,注意坑爹的模数,我们用
代码实现
惊了,现在题解不贴代码过不了审??
#include <bits/stdc++.h>
const int mod = 998244853;
inline int add(int x, int y) { return x + y >= mod ? x + y - mod : x + y; }
inline int sub(int x, int y) { return x - y >= 0 ? x - y : x - y + mod; }
inline int power(int x, int y, int res = 1) {
for (; y; y >>= 1, x = 1ll * x * x % mod) {
if (y & 1) { res = 1ll * res * x % mod; }
} return res;
}
const int N = 1e5 + 5;
int n, m, sx, sy, tx, ty, dx, dy, ans, f[N], fac[N], invf[N];
void initCombin(int n) {
for (int i = fac[0] = 1; i <= n; i++) { fac[i] = 1ll * fac[i - 1] * i % mod; }
invf[n] = power(fac[n], mod - 2);
for (int i = n; i; i--) { invf[i - 1] = 1ll * invf[i] * i % mod; }
}
inline int binom(int n, int m) {
if (n < m) { return 0; }
return 1ll * fac[n] * invf[m] % mod * invf[n - m] % mod;
}
int main() {
std::cin >> n >> m; initCombin(1e5);
tx = n + m; ty = n - m;
for (int i = 0; i <= n; i++) {
sx = 0; sy = i + i;
dx = tx - sx; dy = ty - sy;
if (ty >= i) {
f[i] = binom(n + m, n);
} else {
f[i] = binom(dx, (dx + dy) / 2);
}
}
for (int i = 0; i <= n; i++) { ans = add(ans, 1ll * i * sub(f[i], f[i + 1]) % mod); }
std::cout << ans << std::endl;
return 0;
}