Solution -「LNOI 2022」「洛谷 P8367」盒
Link.
有 个盒子排成一排,第 个盒子内有 个球。球可以在相邻盒子间传递, 与 间的单位传递费用是 。对于所有 ,求通过传递使得 的最小费用和。答案模 。
,。
答案显然是
这个 的高情商理解当然是:我们需要求出每个
注意第二步的绝对值拆得比较有心机,保持求和指标从 开始,使得式子的组合意义更优美。
两项分别算叭。设 。首先利用恒等式 化简 ,此后观察到 的求和是对组合数所有有意义的上指标求和,它应该比较好化简。浅推一下:
其中 是经典组合意义:在 个球中选 个,其中第 个钦定为分隔球,就得到了原乘积式的组合方案。
接下来解决 。先做类似 的前两步化简,然后细看一下,把两个和式单独考虑:
类似于 , 的组合意义为:在 个球里选 个,要求选的第 个球的位置不超过 ; 的组合意义为:在 个球里选 个,要求选的第 个球的位置不超过 。敏锐地注意到: 都可以利用 的一个前驱状态添加或减少边界情况的方案得到。另一方面,原式恰好满足 分别不递减。因此,我们可以维护 和 ,将 随着和式做指针移动。具体地,通过组合意义的理解,不难得到:
可见, 移动到 或者 都是 的,均摊下来,我们就能 求出 。所以总复杂度就是 。
/*+Rainybunny+*/
#include <bits/stdc++.h>
#define rep(i, l, r) for (int i = l, rep##i = r; i <= rep##i; ++i)
#define per(i, r, l) for (int i = r, per##i = l; i >= per##i; --i)
inline char fgc() {
static char buf[1 << 17], *p = buf, *q = buf;
return p == q && (q = buf + fread(p = buf, 1, 1 << 17, stdin), p == q) ?
EOF : *p++;
}
template <typename Tp = int>
inline Tp rint() {
Tp x = 0, s = fgc(), f = 1;
for (; s < '0' || '9' < s; s = fgc()) f = s == '-' ? -f : f;
for (; '0' <= s && s <= '9'; s = fgc()) x = x * 10 + (s ^ '0');
return x * f;
}
template <typename Tp>
inline void wint(Tp x) {
if (x < 0) putchar('-'), x = -x;
if (9 < x) wint(x / 10);
putchar(x % 10 ^ '0');
}
const int MAXN = 5e5, MAXS = 2e6, MOD = 998244353;
int n, a[MAXN + 5], w[MAXN + 5], fac[MAXN + MAXS + 5], ifac[MAXN + MAXS + 5];
inline int mul(const int u, const int v) { return 1ll * u * v % MOD; }
inline void subeq(int& u, const int v) { (u -= v) < 0 && (u += MOD); }
inline int sub(int u, const int v) { return (u -= v) < 0 ? u + MOD : u; }
inline void addeq(int& u, const int v) { (u += v) >= MOD && (u -= MOD); }
inline int add(int u, const int v) { return (u += v) < MOD ? u : u - MOD; }
inline int mpow(int u, int v) {
int ret = 1;
for (; v; u = mul(u, u), v >>= 1) ret = mul(ret, v & 1 ? u : 1);
return ret;
}
inline void init(const int s) {
fac[0] = 1;
rep (i, 1, s) fac[i] = mul(i, fac[i - 1]);
ifac[s] = mpow(fac[s], MOD - 2);
per (i, s - 1, 0) ifac[i] = mul(i + 1, ifac[i + 1]);
}
inline int bino(const int u, const int v) {
return v < 0 || u < v ? 0 : mul(fac[u], mul(ifac[v], ifac[u - v]));
}
int main() {
init(MAXN + MAXS);
for (int T = rint(); T--;) {
n = rint();
rep (i, 1, n) a[i] = a[i - 1] + rint();
rep (i, 1, n - 1) w[i] = rint();
int ans = 0, S = a[n];
int fx = 0, fy = 0, fv = bino(S + n - 2, n - 1);
int gx = 1, gy = 0, gv = bino(S + n - 2, n - 2);
rep (i, 1, n - 1) {
addeq(ans, mul(w[i], sub(mul(i, bino(S + n - 1, n)),
mul(a[i], bino(S + n - 1, n - 1)))));
while (fx < i) {
++fx;
subeq(fv, mul(bino(fx + fy, fx),
bino(S + n - 2 - fx - fy, n - fx)));
}
while (fy < a[i] - 1) {
++fy;
addeq(fv, mul(bino(fx + fy, fx),
bino(S + n - 2 - fx - fy, n - 1 - fx)));
}
while (gx < i) {
++gx;
subeq(gv, mul(bino(gx + gy - 1, gx - 1),
bino(S + n - 1 - gx - gy, n - gx)));
}
while (gy < a[i]) {
++gy;
addeq(gv, mul(bino(gx + gy - 1, gx - 1),
bino(S + n - 1 - gx - gy, n - 1 - gx)));
}
addeq(ans, mul(mul(2, w[i]),
sub(mul(a[i], gv), mul(i, fy == a[i] - 1 ? fv : 0))));
}
wint(ans), putchar('\n');
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现