(旧存档) 杭电多校第六场-A题
A 数学 和式变换
题意
有一串长度为 $n$ 的串 $s$, 随机选择有序对 $(x, y)$ 且 $1 \le x \le y \le n$, 求 $\frac{\sum \limits_{i=x}^{y}s_i}{y - x + 1}$ 的期望
思路
注意:这里的随机不是指 $x, y$ 在 $[1, n]$ 均匀分布且随机, 而是指满足 $1 \le x \le y \le n$ 的有序对 $(x, y)$ 中随机抽取。
设:$F(x, y) = \frac{\sum \limits_{i=x}^{y}s_i}{y - x + 1}$, 那么:
$E(F(x, y)) = \binom{n}{2}^{-1}\sum \limits_{i=1}^{n} \sum \limits_{j=i}^{n}\frac{sum[j] - sum[i - 1]}{j-i+1}$
由于分母太难看,不妨换成 $len = j - i + 1$, 对 $i$ 进行换元,有:
$\frac{sum[j] - sum[i - 1]}{j-i+1} = \frac{sum[j] - sum[j - len]}{len}$
然后考虑置换和式的变量,和式是由以下方程围成的空间:
$i = 1$, $j = n$, $j = i$
置换 $i$ 后,和式是由以下方程围成的空间:
$j = len$, $j = n$,$len = 1$
先计算 $j$,再计算 $len$,得到:
$E(F(x, y)) = \binom{n}{2}^{-1}\sum \limits_{len=1}^{n} \sum \limits_{j=len}^{n}\frac{sum[j] - sum[j - len]}{len} = \binom{n}{2}^{-1}\sum \limits_{len=1}^{n} \frac{suffix[len] - prefix[n - len]}{len}$
其中,suffix 是 sum 的后缀和,prefix 是 sum 的前缀和,我们可以 $O(n)$计算 sum 以及 sum 的前后缀和,以及 $1$ 到 $n$ 的逆元,$O(n)$ 算出上列式子,时间复杂度 $O(n)$
代码
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 2e5 + 5, MOD = 1e9 + 7;
ll sum[N], inv[N], prefix[N], suffix[N];
ll quick_pow(ll a, ll b) {
ll ret = 1;
while (b) {
if (b & 1) ret = ret * a % MOD;
a = a * a % MOD;
b >>= 1;
}
return ret;
}
void init() {
inv[1] = 1;
for (int i = 2; i < N; ++i) {
inv[i] = (MOD - MOD / i) * 1ll * inv[MOD % i] % MOD;
}
}
int main() {
int t;
init();
scanf("%d", &t);
while (t--) {
int n;
scanf("%d", &n);
sum[0] = prefix[0] = suffix[n + 1] = 0;
for (int i = 1; i <= n; ++i) {
scanf("%lld", &sum[i]);
sum[i] = (sum[i - 1] + sum[i]) % MOD;
prefix[i] = (prefix[i - 1] + sum[i]) % MOD;
}
for (int i = n; i >= 1; --i) {
suffix[i] = (suffix[i + 1] + sum[i]) % MOD;
}
ll ans = 0;
for (int len = 1; len <= n; ++len) {
ans = (ans + (suffix[len] - prefix[n - len]) % MOD * inv[len]) % MOD;
}
ans = ans * quick_pow(1ll * n * (n + 1) / 2 % MOD, MOD - 2) % MOD;
ans = (ans + MOD) % MOD;
printf("%lld\n", ans);
}
return 0;
}