一、题目
二、解法
设最小子段数为
B
(
x
)
B(x)
B(x),设
I
i
(
x
)
=
[
x
i
≠
x
i
−
1
]
I_i(x)=[x_i\not=x_{i-1}]
Ii(x)=[xi=xi−1],则有这样的关系式:
B
(
x
)
=
∑
i
=
1
n
I
i
(
x
)
B(x)=\sum_{i=1}^nI_i(x)
B(x)=i=1∑nIi(x)所求是
E
(
B
(
x
)
2
)
E(B(x)^2)
E(B(x)2),我们来推导一波:
=
E
(
∑
i
=
1
n
I
i
(
x
)
∑
j
=
1
n
I
j
(
x
)
)
=E(\sum_{i=1}^nI_i(x)\sum_{j=1}^nI_j(x))
=E(i=1∑nIi(x)j=1∑nIj(x))
=
E
(
∑
i
=
1
n
∑
j
=
1
n
I
i
(
x
)
I
j
(
x
)
)
=E(\sum_{i=1}^n\sum_{j=1}^nI_i(x)I_j(x))
=E(i=1∑nj=1∑nIi(x)Ij(x))
=
∑
i
=
1
n
∑
j
=
1
n
E
(
I
i
(
x
)
I
j
(
x
)
)
=\sum_{i=1}^n\sum_{j=1}^nE(I_i(x)I_j(x))
=i=1∑nj=1∑nE(Ii(x)Ij(x))现在我们来分类讨论一下
E
(
I
i
(
x
)
I
j
(
x
)
)
E(I_i(x)I_j(x))
E(Ii(x)Ij(x)):
- i = j i=j i=j,由于 I i ( x ) I_i(x) Ii(x)只能是 0 / 1 0/1 0/1,所以它等于 E ( I i ( x ) ) E(I_i(x)) E(Ii(x))
- ∣ i − j ∣ > 1 |i-j|>1 ∣i−j∣>1,由于 I i ( x ) I_i(x) Ii(x)和 I j ( x ) I_j(x) Ij(x)互不影响,所以等于 E ( I i ( x ) ) E ( I j ( x ) ) E(I_i(x))E(I_j(x)) E(Ii(x))E(Ij(x))
- ∣ i − j ∣ = 1 |i-j|=1 ∣i−j∣=1,设 q i = E ( x i = x i − 1 ) = min ( r i , r i − 1 ) − max ( l i . l i − 1 ) ( r i − l i ) ( r i − 1 l i − 1 ) q_i=E(x_i=x_{i-1})=\frac{\min(r_i,r_{i-1})-\max(l_i.l_{i-1})}{(r_i-l_i)(r_{i-1}l_{i-1})} qi=E(xi=xi−1)=(ri−li)(ri−1li−1)min(ri,ri−1)−max(li.li−1),我们要求的是 E ( x i − 1 ≠ x i & x i ≠ x i + 1 ) E(x_{i-1}\not=x_{i}\&x_{i}\not=x_{i+1}) E(xi−1=xi&xi=xi+1),利用简单的容斥原理,可以得出所求为 1 − q i − q i + 1 − E ( x i − 1 = x i & x i = x i + 1 ) 1-q_i-q_{i+1}-E(x_{i-1}=x_{i}\&x_i=x_{i+1}) 1−qi−qi+1−E(xi−1=xi&xi=xi+1),最后一项利用类似的方法算即可。
不难发现总时间复杂度是 O ( n ) O(n) O(n)的,贴个代码
#include <cstdio>
#include <iostream>
using namespace std;
#define int long long
const int M = 200005;
const int jzm = 1e9+7;
int read()
{
int x=0,flag=1;
char c;
while((c=getchar())<'0' || c>'9') if(c=='-') flag=-1;
while(c>='0' && c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return x*flag;
}
int n,ans,sum,l[M],r[M],q[M],E[M];
int qkpow(int a,int b)
{
int r=1;
while(b>0)
{
if(b&1) r=r*a%jzm;
a=a*a%jzm;
b>>=1;
}
return r;
}
int calc(int i)
{
int ret=0;
if(i>1)
{
int t=min(r[i],min(r[i-1],r[i+1]))-max(l[i],max(l[i-1],l[i+1]));
ret=max(0ll,t*qkpow((r[i]-l[i])*(r[i-1]-l[i-1])%jzm*(r[i+1]-l[i+1])%jzm,jzm-2)%jzm);
}
return (1-q[i]-q[i+1]+ret)%jzm;
}
signed main()
{
n=read();
for(int i=1;i<=n;i++)
l[i]=read();
for(int i=1;i<=n;i++)
{
r[i]=read()+1;
int R=min(r[i],r[i-1]),L=max(l[i],l[i-1]);
q[i]=max(0ll,(R-L)*qkpow((r[i]-l[i])*(r[i-1]-l[i-1])%jzm,jzm-2)%jzm);
E[i]=(1-q[i]+jzm)%jzm;
sum=(sum+E[i])%jzm;
}
for(int i=1;i<=n;i++)
{
int tmp=sum;
for(int j=max(1ll,i-1);j<=min(n,i+1);j++)
tmp=(tmp-E[j])%jzm;
ans=(ans+E[i]*tmp+E[i])%jzm;
if(i>1) ans=(ans+calc(i-1))%jzm;
if(i<n) ans=(ans+calc(i))%jzm;
}
printf("%d\n",(ans+jzm)%jzm);
}