ARC124E
传出球的最小值不为 0 时,可以将所有人传出球的数量同时减一,得到的序列不变。
所以得出结论,所有人传出的球的数量的最小值必定为 0。
观察答案的实际含义:最终序列中从每个人手上选出一个球的方案数。
每个人的球只有两种来源:自己原来没有传出去的球/上一个人传过来的球。启示我们记录球的来源以 DP。
状态的定义有点奇怪:fi,0 表示第 i 个人从自己处选择球且不计第 i 个人选择方案时前 i−1 个人的选球方案数,fi,1 表示第 i 个人从前面人选择球且计入第 i 个人的选球方案时的方案数。
转移分为四种情况:
(i,0)→(i+1,0),此时要计算第 i 个人的选择方案,剩下几个球就有几种转移方案,转移系数为 ∑aik=1k。
(i,0)→(i+1,1),此时要计算第 i 个人和第 i+1 个人的选择方案,转移系数为 ∑ai−1k=1k×(ai−k)。
(i,1)→(i+1,0),此时要计算第 i 个人的传球方案,转移系数为送出几个球,即 ∑aik=01=ai+1。
(i,1)→(i+1,1),此时要计算第 i+1 个人的选择方案,转移系数为 ∑aik=1k。
因为是一个环,那么可以枚举 1 的决策然后开始 DP。
注意这样子统计出来的并不要求传球数最小为 0 那么可以再编一个传球数最小为 1 的式子写出来即可。
Code:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100005, mod = 998244353, inv2 = (mod + 1) / 2, inv6 = (mod + 1) / 6;
int n;
int a[N], f[N][2];
void add(int &a, int b) {
a += b;
if (a >= mod) a -= mod;
if (a < 0) a += mod;
}
int calc1(int x) { return 1ll * x * (x + 1) % mod * inv2 % mod; }
int calc2(int x) { return 1ll * x * (x + 1) % mod * (2 * x + 1) % mod * inv6 % mod; }
int solve(int x, int y) {
memset(f, 0, sizeof f);
f[1][x] = 1;
for (int i = 1; i <= n; ++i) {
add(f[i + 1][0], 1ll * f[i][0] * calc1(a[i] - y) % mod), add(f[i + 1][0], 1ll * f[i][1] * (a[i] - y + 1) % mod);
add(f[i + 1][1], 1ll * f[i][0] * ((1ll * a[i] * calc1(a[i]) % mod - calc2(a[i]) + mod) % mod) % mod), add(f[i + 1][1], 1ll * f[i][1] * calc1(a[i]) % mod);
}
return f[n + 1][x];
}
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
int ans = 0; add(ans, solve(1, 0)), add(ans, solve(0, 0));
add(ans, -solve(1, 1)), add(ans, -solve(0, 1));
printf("%d", ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话