【2020杭电多校】第六场 Road To The 3rd Building 枚举
题意
给出 n 个数字,定义一个区间 [ l , r ] 的价值为区间和 / 区间大小。现在随机选择一个区间,问区间价值的期望。
思路
按照区间长度枚举所有长度的区间的贡献,最后乘上 区间个数的逆元
区间长度固定时,每个数字在该长度区间出现的次数先递增,不变,然后递减。
当区间长度为 i 时,前 \(min(i, n - i + 1)-1\) 个的出现次数是从 1 递增的,后面 \(min(i, n - i + 1)-1\) 个是递减的,中间的出现次数相等,均为\(min(i, n - i + 1)\) 次。
PS:区间个数之前想成了\(n*(n-1)\),半天找不到 bug。
代码
#include <bits/stdc++.h>
#define fuck system("pause")
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
const int mod = 1e9+7;
const double eps = 1e-6;
const int inf = 0x3f3f3f3f;
const int N = 2e5 + 10;
ll arr[N];
ll pre[N],pre2[N],suf[N];
ll qpow(ll a, ll b)
{
ll ans = 1;
a %= mod;
while (b) {
if (b & 1) {
ans = (ans * a) % mod;
}
b >>= 1;
a = a * a % mod;
}
return ans % mod;
}
int main(){
ll T;
scanf("%d", &T);
while(T--){
memset(suf, 0, sizeof(suf));
ll n;
scanf("%d", &n);
for (ll i = 1; i <= n;i++){
scanf("%d", &arr[i]);
pre[i] = (pre[i - 1] + arr[i]) % mod;
pre2[i] = (pre2[i - 1] + i * arr[i]%mod) % mod;
}
for (ll i = n; i;i--){
suf[i] = (suf[i + 1] +arr[i]* (n - i + 1)%mod) % mod;
}
ll sum = 0;
for (ll i = 1;i<=n;i++){
ll num = min(i, n - i + 1);
ll now = (pre2[num - 1] + (pre[n - num + 1] - pre[num - 1] + mod) % mod * num % mod + suf[n - num + 2]) % mod * qpow(i, mod - 2) % mod;
sum = (sum + now) % mod;
}
printf("%lld\n", sum*qpow(1LL*n*(n+1)/2,mod-2)%mod);
}
return 0;
}