CF1187F Expected Square Beauty
Expected Square Beauty
有一个长度为 n 的数列,第 i 个数的取值范围为 \([l_i,r_i]\) ,定义一个数列的价值为这个数列极长连续相同段的个数,求一个数列价值的平方期望,对 \(10^9+7\) 取模 。
n≤200000 。
题解
https://codeforces.com/blog/entry/68111
As usual with tasks on an expected value, let's denote \(I_i(x)\) as indicator function: \(I_i(x) = 1\) if \(x_i \neq x_{i - 1}\) and \(0\) otherwise; \(I_1(x) = 1\). Then we can note that \(B(x) = \sum\limits_{i = 1}^{n}{I_i(x)}\). Now we can make some transformations:
Now we'd like to make some casework:
-
if |i - j| > 1 (i and j aren't consecutive) then \(I_i(x)\) and \(I_j(x)\) are independent, that's why \(E(I_i(x) I_j(x)) = E(I_i(x)) E(I_j(x))\);
-
if i = j then \(E(I_i(x) I_i(x)) = E(I_i(x))\);
-
|i - j| = 1 need further investigation.
For the simplicity let's transform segment \([l_i, r_i]\) to \([l_i, r_i)\) by increasing \(r_i = r_i + 1\).
Let's denote \(q_i\) as the probability that \(x_{i-1} = x_i\):
and \(q_1 = 0\). Let's denote \(p_i = 1 - q_i\). In result, \(E(I_i(x)) = p_i\).
The final observation is the following: \(E(I_i(x) I_{i + 1}(x))\) is equal to the probability that \(x_{i - 1} \neq x_i\) and \(x_i \neq x_{i + 1}\) and can be calculated by inclusion-exclusion principle:
, where
In result,
and can be calculated in \(O(n \log{MOD})\) time.
CO int N=2e5+10;
int L[N],R[N];
int Q[N],E[N];
int calc(int i,int j,int k){
int prob=0;
if(i>=1){
int l=max(L[i],max(L[j],L[k])),r=min(R[i],min(R[j],R[k]));
if(l<r) prob=mul(r-l,fpow(mul(R[i]-L[i],
mul(R[j]-L[j],R[k]-L[k])),mod-2));
}
return add(1,add(mod-Q[j],add(mod-Q[k],prob)));
}
int main(){
int n=read<int>();
for(int i=1;i<=n;++i) read(L[i]);
for(int i=1;i<=n;++i) read(R[i]),++R[i];
int sum=0;
for(int i=1;i<=n;++i){
int l=max(L[i],L[i-1]),r=min(R[i],R[i-1]);
if(l<r) Q[i]=mul(r-l,fpow(mul(R[i-1]-L[i-1],R[i]-L[i]),mod-2));
E[i]=add(1,mod-Q[i]);
sum=add(sum,E[i]);
}
int ans=0;
for(int i=1;i<=n;++i){
int res=sum;
for(int j=max(i-1,1);j<=min(i+1,n);++j) res=add(res,mod-E[j]);
ans=add(ans,mul(E[i],res));
ans=add(ans,E[i]);
if(i>1) ans=add(ans,calc(i-2,i-1,i));
if(i<n) ans=add(ans,calc(i-1,i,i+1));
}
printf("%d\n",ans);
return 0;
}