推公式+期望 [ 2020 Multi-University Training Road To The 3rd Building]
阿新 • • 發佈:2020-08-06
推公式+期望 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\n",ans); } return 0; }