CF1187F Expected Square Beauty

一、题目

点此看题

二、解法

设最小子段数为 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=xi1],则有这样的关系式:
B ( x ) = ∑ i = 1 n I i ( x ) B(x)=\sum_{i=1}^nI_i(x) B(x)=i=1nIi(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=1nIi(x)j=1nIj(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=1nj=1nIi(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=1nj=1nE(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 ij>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 ij=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=xi1)=(rili)(ri1li1)min(ri,ri1)max(li.li1),我们要求的是 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(xi1=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}) 1qiqi+1E(xi1=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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值