【2020杭电多校】第六场 Road To The 3rd Building 枚举

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;
}

posted @ 2020-08-07 12:04  Valk3  阅读(220)  评论(0编辑  收藏  举报