AGC028 B Removing Blocks 期望 逆元 字首和
阿新 • • 發佈:2018-11-23
題目連結
題意:
給你
個數,現在有
次操作,每次操作選擇一個未選擇的數,然後加上從它到它後面最後一個連續沒選過的數的權值和,並標記這個數為選過。我們發現,我們有
種可能的操作,求這
種操作得到的權值和的和。
題解:
atcoder真的是好題無限啊!這題真不錯,我一開始想這題算每一個數對答案的貢獻,想嘗試用組合數,發現做不出來。然後感慨這題似乎可以出成期望題啊,然後去看題解,發現真的是用期望做。。
我們設 為 到 這個區間完好,在操作時選了 的概率,那麼對於所有的 ,我們設 對答案的期望貢獻次數是 , 這個位置的值是 ,那麼有 ,對於隨機操作,我們期望得到的答案就是 ,最後再成一個 就是最後的答案了。
我們發現, 是 中最先出現的概率相當於是在區間 中先選出 的概率,即 ,那麼我們對 求字首和,當然需要先 的求逆元。然後我們可以算出 前面(不包含 本身)的 的字首和 和 後面(包含 本身)的所有 的和 。其中前一個減1是因為要不包含 本身。於是就可以用上面說的方法求出答案了。
程式碼:
#include <bits/stdc++.h>
using namespace std;
const long long mod=1e9+7;
int n;
long long a[100010],ni[100010],s[100010],ans,jie[100010];
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%lld",&a[i]);
ni[1]=1;
for(int i=2;i<=n;++i)
ni[i]=(mod-mod/i)*ni[mod%i]%mod;
for(int i=1;i<=n;++i)
s[i]=(s[i-1]+ni[i])%mod;
for(int i=1;i<=n;++i)
ans=(ans+s[n-i+1]*a[i]%mod+(s[i]-1)*a[i]%mod)%mod;
jie[0]=1;
for(int i=1;i<=n;++i)
jie[i]=jie[i-1]*i%mod;
ans=(ans*jie[n])%mod;
printf("%lld\n",ans);
return 0;
}