推公式+期望 2020 Multi-University Training Road To The 3rd Building
题目大意:
每一个点有一个权值 (s_i) ,定义一个计划是一对 ((i,j)) (1<=i<=j<=n) ,计划的可爱程度是 (frac{1}{j-i+1}sum_{k=i}^j s_k) ,问选择一个计划的期望可爱程度是多少?
题解:
期望等于概率乘以可爱程度这个权值,又因为选每一个的期望都是一样的,所以概率是一样的,只要求出所有的权值之和即可。
答案就是:
(s_1) 的贡献 :(s1+frac{s1+s2}{2}+frac{s1+s2+s3}{3}...)
(s_2) 的贡献:(s2+frac{s2+s3}{2}+frac{s2+s3+s4}{3}...)
...
所以对于 (frac{1}{i}) 它要乘的就是 (sum[i]) ((sum[i]) 表示 ([1,n]) 所有连续长度为 (i) 的权值之和)
所以求出这个 (sum[i]) ,然后再乘上 (inv[i]) 即是可爱程度之和,然后乘上概率即可。
#include <bits/stdc++.h>
#define debug(x) cout<<"debug:"<<#x<<" = "<<x<<endl;
using namespace std;
typedef long long ll;
const int maxn = 2e5+10;
const int mod = 1e9+7;
long long inv[maxn],pre[maxn],sum[maxn],a[maxn];
int c[maxn];
void init(int n) {
c[0] = 1;
for (int i = 1; i <= n; i++) c[i] = c[i - 1] * (n - i + 1) / i;
inv[1] = 1;
for (int i = 2; i <= n + 1; i++) {
inv[i] = (mod - mod / i) * inv[mod % i] % mod;
}
}
long long finv(long long x,long long mod)
{
long long k=mod-2,ans=1;
while(k)
{
if (k&1) ans=ans*x%mod;
x=x*x%mod;
k>>=1;
}
return ans;
}
int main(){
int T;
scanf("%d",&T);
while(T--) {
ll n;
scanf("%lld", &n);
init(n - 1);
for (int i = 1, x; i <= n; i++) {
scanf("%lld", &a[i]);
pre[i] = (pre[i - 1] + a[i]) % mod;
}
ll last = a[n];
sum[1] = pre[n];
for (int i = 2; i <= n; i++) {
sum[i] = ((sum[i - 1] - last + pre[n] - pre[i - 1]) % mod + mod) % mod;
last = (last + a[n - i + 1]) % mod;
}
ll ans = 0;
for(int i=1;i<=n;i++) {
ans = (ans+inv[i]*sum[i]%mod)%mod;
}
n = (n*(n-1)/2+n)%mod;
ans = ans*finv(n,mod)%mod;
printf("%lld
",ans);
}
return 0;
}