先考虑最后的站位数组 p 的形状。所有人的位置应该构成连续的一段区间,每次操作 x 时,若 x 在区间内部,则相当于是将 x−1,x,x+1 位置上的所有人都缩成一个点。x 在区间边缘的话,则比较特殊,相当于是只影响了两个位置。
通过归纳,可以得出一个必要条件:
所有人的位置构成连续的一段区间。
区间边缘的人数随意,区间内部的人数必为奇数,区间人数总和为 n。
同时我们发现,该条件也是充分的,因为任意一个满足该必要条件的位置数组 p 都可以被构造出来:从左往右构造。若边缘位置人数为 v,则只需要放置 v−1 次景点;若中间位置人数为 v,则只需要放置 2v−1 次景点。等整个位置数组 p 的形状构造出来以后,可以通过在 1 或 n 处放置景点,从而调整区间的起始位置。
using s64 = longlong; using u64 = unsignedlonglong;
/* 取 min */ template <classT> inlinevoidchmin(T &x, const T &y){ if (x > y) { x = y; } } /* 取 max */ template <classT> inlinevoidchmax(T &x, const T &y){ if (x < y) { x = y; } }
/* ----- ----- ----- 正文 ----- ----- ----- */
constint mod = 998244353; // 模数需根据实际问题调整
/* 模意义下 加法 */ inlinevoidadd(int &x, constint &y){ x += y; if (x >= mod) { x -= mod; } }
/* 模意义下 减法 */ inlinevoiddec(int &x, constint &y){ x -= y; if (x < 0) { x += mod; } }
/* 模意义下 乘法 */ inlinevoidmul(int &x, constint &y){ x = 1ll * x * y % mod; }
/* 快速幂 */ constexprintqpow(int a, int b, int p){ int ans = 1; for (; b; b >>= 1) { if (b & 1) ans = 1ll * ans * a % p; a = 1ll * a * a % p; } return ans; }
constint N = 200100;
int n; int a[N];
int pre[N], pre2[N];
structBinomCoef { std::vector<int> fact, facv;
voidinit(constint &n){ fact.resize(n + 1), facv.resize(n + 1); fact[0] = 1; for (int i = 1; i <= n; i ++) { fact[i] = 1ll * fact[i - 1] * i % mod; }
facv[n] = qpow(fact[n], mod - 2, mod); for (int i = n - 1; i >= 0; i --) { facv[i] = 1ll * facv[i + 1] * (i + 1) % mod; } }
intbinom(int n, int m){ if (n < m || m < 0) { return0; } return1ll * facv[m] * facv[n - m] % mod * fact[n] % mod; } } bc;
voidwork(){ std::cin >> n;
for (int i = 1; i <= n; i ++) { std::cin >> a[i]; a[i] %= mod; }
bc.init(n * 2);
for (int i = 1; i <= n; i ++) { add(pre[i] = pre[i - 1], a[i]); add(pre2[i] = pre2[i - 1], pre[i]); }
int ans = 1ll * n * pre[n] % mod;
for (int k = 2; k <= n; k ++) { int sum = 0; add(sum, pre2[n]), dec(sum, pre2[k - 1]); dec(sum, pre2[n - k]);
// std::cout << sum << '\n';
for (int x = 1; x <= 2; x ++) { for (int y = 1; y <= 2; y ++) { int S = n - x - y - (k - 2); if (S & 1) { continue; }
S >>= 1;
int val = 1ll * S * qpow(k, mod - 2, mod) % mod; int cnt = bc.binom(S + k - 1, k - 1);
add(ans, (2ll * val + 1) * cnt % mod * sum % mod); if (x > 1) { add(ans, 1ll * cnt * pre[n - k + 1] % mod); } if (y > 1) { add(ans, 1ll * cnt * (pre[n] - pre[k - 1] + mod) % mod); } } } }