Groundhog and Gaming Time

题目描述

样例

input:
6
2 2
1 2
1 4
1 5
3 5
3 6
output:
405536771

题目大意

给定nnn个区间(Li,Ri)(L_i,R_i)(Li​,Ri​),每个区间有12\frac{1}{2}21​的概率取到,假设取了mmm个,求:
E(∣(L1,R1)∩(L2,R2)∩(L3,R3)...∩(Lm,Rm)∣2)E(|(L_1,R_1)\cap(L_2,R_2)\cap(L_3,R_3)...\cap(L_m,R_m)|^2)E(∣(L1​,R1​)∩(L2​,R2​)∩(L3​,R3​)...∩(Lm​,Rm​)∣2)
其中E(A)E(A)E(A)表示AAA的期望。

分析

首先我们看到期望先回顾期望的几种解法:
1、E(A)=P(A)∗A1、E(A)=P(A)*A1、E(A)=P(A)∗A 显然不行,如果所有的情况枚举显然超时了。
2、解方程2、解方程2、解方程 这题也没有想再来一瓶那样的可以列出简单的方程,否定。
3、期望dp3、期望dp3、期望dp 这是官方的做法,比较繁琐,但是也可以做。
4、解决单位的期望后累加4、解决单位的期望后累加4、解决单位的期望后累加 这是本篇博客介绍的做法,代码简单。

我们首先来考虑去掉平方之后怎么做。其实是比较简单的,我们不妨画个图简绍一下。

如果有①②③三个区间,我们可以将它们离散化在一条直线上,然后左右端点都分开,得到了1∼51\sim 51∼5的小线段,然后我们对于每个区间都考虑一下:
比如1号线段,如果要取到1号,那么肯定要取区间①,并且②③都不能取,否则∩就不是1号了,因此其概率是18\frac{1}{8}81​,总共8种取法,一种满足,因此期望是∣1区间∣8\frac{|1区间|}{8}8∣1区间∣​。
同样的,可以得到:
2号,概率是取①,取②或者取①和②,为38\frac{3}{8}83​,期望就乘上长度就可以了……

那么对于一段线段,我们可以统计有多少区间是覆盖它的,然后算一下再除以所有的情况就可以了。

以上是去掉平方之后的,但是题目中是有平方的,因此,我们需要将平方搞回去。那么我们假设对于区间iii的期望是xix_ixi​,则有:
E=(x1+x2+...+xn)2E=(x_1+x_2+...+x_n)^2E=(x1​+x2​+...+xn​)2
=x1(x1+x2+...+xn)+x2(x1+x2+...+xn)+...+xn(x1+x2+...+xn)\,\,\,\,\,\,=x_1(x_1+x_2+...+x_n)+x_2(x_1+x_2+...+x_n)+...+x_n(x_1+x_2+...+x_n)=x1​(x1​+x2​+...+xn​)+x2​(x1​+x2​+...+xn​)+...+xn​(x1​+x2​+...+xn​)
可以发现,对于一个xix_ixi​,可以直接在平方中给它拆开来。
具体一点,就拿上面的栗子:
我们考虑x2x_2x2​,那么有这些式子:
E=(x1+x2)2+x22+(x2+x3+x4)2E=(x_1+x_2)^2+x_2^2+(x_2+x_3+x_4)^2E=(x1​+x2​)2+x22​+(x2​+x3​+x4​)2//即取区间①,区间①②,区间②的情况累加
这里我们考虑x2x_2x2​对答案的贡献有以下:
x2(x1+x2)x_2(x_1+x_2)x2​(x1​+x2​)//取区间①
x2∗x2x_2*x_2x2​∗x2​//取区间①②
x2(x2+x3+x4)x_2(x_2+x_3+x_4)x2​(x2​+x3​+x4​)//取区间②
那么经过上面去掉平方的经验,x2x_2x2​应该是很好求的,重点是解决后面一坨东西怎么算。

同样的,我们考虑这些后面的一段在给定的区间中出现了几次。
假设我当前枚举到线段QQQ,并且它出现在区间中aaa次,则有:
E(Q)=2a−12n∗∣Q∣E(Q)=\frac{2^a-1}{2^n}*|Q|E(Q)=2n2a−1​∗∣Q∣
显然,不能全部都不取,这里的式子都比较好推的,可以结合上面的图示理解一下。
那么对于所有的线段PiP_iPi​贡献为:
贡献=∑E(Pi)=\sum E(P_i)=∑E(Pi​)
=∣Pi∣∗∑j(2aj−12n∗∣Qj∣)\,\,\,\,\,\,\,\,\,\,=|P_i|*\sum_j(\frac{2^{a_j}-1}{2^n}*|Q_j|)=∣Pi​∣∗∑j​(2n2aj​−1​∗∣Qj​∣)
=∣Pi∣∗∑j(2aj2n∗∣Qj∣)−不取的期望\,\,\,\,\,\,\,\,\,\,=|P_i|*\sum_j(\frac{2^{a_j}}{2^n}*|Q_j|)-不取的期望=∣Pi​∣∗∑j​(2n2aj​​∗∣Qj​∣)−不取的期望
那么中间的那段可以用线段树来维护,然后最后再减去不取的。
更多的细节看代码。

代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll MAX=1e9+1;
const int MAXN=1e6+10;
const int MOD=998244353;
ll inv,p[MAXN],l[MAXN],r[MAXN],idl[MAXN],idr[MAXN];
ll ksm(ll a,ll p){ll ret=1;while(p){if(p&1) ret=ret*a%MOD;a=a*a%MOD,p>>=1;}return ret;}
struct tree{int l,r;ll sum,inc;
}tr[MAXN<<2];
void build(int i,int l,int r){tr[i].l=l;tr[i].r=r;tr[i].sum=p[r+1]-p[l]%MOD;tr[i].inc=1;if(l==r) return;int mid=l+r>>1;build(i<<1,l,mid);build(i<<1|1,mid+1,r);
}
void update(int i,int l,int r,ll v){if(tr[i].l>=l&&tr[i].r<=r){tr[i].sum=tr[i].sum*v%MOD;tr[i].inc=tr[i].inc*v%MOD;return;}int mid=tr[i].l+tr[i].r>>1;if(r<=mid) update(i<<1,l,r,v);else if(l>mid) update(i<<1|1,l,r,v);else update(i<<1,l,mid,v),update(i<<1|1,mid+1,r,v);tr[i].sum=(tr[i<<1].sum+tr[i<<1|1].sum)%MOD*tr[i].inc%MOD;
}//线段树区间乘
bool cmpl(int x,int y){return l[x]<l[y];}
bool cmpr(int x,int y){return r[x]<r[y];}
int main()
{inv=ksm(2,MOD-2);//因为有除法所以用逆元int n,m=2;scanf("%d",&n);p[1]=0;p[2]=MAX;//防止错误,将线段的左右端点赋值为0和inffor(int i=1;i<=n;i++){scanf("%d%d",&l[i],&r[i]);p[++m]=l[i];p[++m]=++r[i];//存入所有区间的左右端点,这样可以像上面图示一样分开}sort(p+1,p+1+m);m=unique(p+1,p+1+m)-p-1;//离散化build(1,1,m-1);//线段树存储的是线段的长度,初始的时候都是1for(int i=1;i<=n;i++){l[i]=lower_bound(p+1,p+1+m,l[i])-p;r[i]=lower_bound(p+1,p+1+m,r[i])-p;idl[i]=idr[i]=i;//这是记录从左边数第i个左右端点所属的区间的编号}sort(idl+1,idl+1+n,cmpl);sort(idr+1,idr+1+n,cmpr);//然后按照这个排序int li=1,ri=1;ll ans=0;for(int i=1;i<m;i++){//遍历区间[i,i+1],维护包含该区间的线段的交集的期望。这个期望通过计算所有区间的贡献和得到 //从m个线段,找出a个线段包含区间[i,i+1]。计算这a个线段的交集的期望,等于每个区间的贡献总和。//a个线段,有b个线段覆盖区间[j,j+1],则区间[j,j+1]的贡献=长度*(2^b-1)/2^n。其中-1和/2^n最后再去除 for(li;l[idl[li]]<=i&&li<=n;li++)update(1,l[idl[li]],r[idl[li]]-1,2);//乘上所有在这个区间内的线段贡献for(ri;r[idr[ri]]<=i&&ri<=n;ri++)update(1,l[idr[ri]],r[idr[ri]]-1,inv);//除去所有不在这个区间内的,用inv代替除ans=(ans+tr[1].sum*(p[i+1]-p[i])%MOD)%MOD;//然后累加贡献}ans=(ans-MAX%MOD*MAX%MOD+MOD)%MOD;//这里是去除最后都不取的情况,即处理上面说的-1ans=(ans*ksm(inv,n))%MOD;//这里是/2^nprintf("%lld\n",ans%MOD);
}

END

这段代码有其他的一些注释,可以参考。

这题的思路真的比较厉害,这属于套娃的思想,在原来没有平方的基础上,把平方又拆成同样的问题,太强了。

2020牛客暑期多校训练营Groundhog and Gaming Time(数学期望,线段树,逆元)相关推荐

  1. 2019牛客暑期多校训练营(第一场场)_I题Points Division(线段树+DP维护区间最大值)

    题目链接: https://ac.nowcoder.com/acm/contest/881/I 题意: 给你n个点,每个点的坐标为(xi,yi),有两个权值ai,bi. 现在要你将它分成A,B两部分, ...

  2. 2021牛客暑期多校训练营1 J-Journey among Railway Stations(线段树+思维转化)

    J-Journey among Railway Stations 注意区间合并时是否可行信息的合并. 假设线段树当前左节点lll维护的区间是[L,mid][L,\text{mid}][L,mid],右 ...

  3. E Groundhog Chasing Death(2020牛客暑期多校训练营(第九场))(思维+费马小定理+质因子分解)

    E Groundhog Chasing Death(2020牛客暑期多校训练营(第九场))(思维+费马小定理+质因子分解) 链接:https://ac.nowcoder.com/acm/contest ...

  4. 2020牛客暑期多校训练营(第六场)

    2020牛客暑期多校训练营(第六场) 额,睡了一下午,直接错过了比赛... 文章目录 A African Sort 题意: 题解: 代码: B Binary Vector C Combination ...

  5. 2020牛客暑期多校训练营(第四场)

    2020牛客暑期多校训练营(第四场) 这场属实有点难受 文章目录 A Ancient Distance B Basic Gcd Problem 题目 代码: C Count New String D ...

  6. 2020牛客暑期多校训练营(第一场)

    文章目录 A B-Suffix Array B Infinite Tree C Domino D Quadratic Form E Counting Spanning Trees F Infinite ...

  7. 2020牛客暑期多校训练营(第二场)

    2020牛客暑期多校训练营(第二场) 最烦英语题 文章目录 A All with Pairs B Boundary C Cover the Tree D Duration E Exclusive OR ...

  8. 2020牛客暑期多校训练营(第七场)J.Pointer Analysis

    2020牛客暑期多校训练营(第七场)J.Pointer Analysis 题目链接 题目描述 Pointer analysis, which aims to figure out which obje ...

  9. 2020牛客暑期多校训练营(第三场)A.Clam and Fish

    2020牛客暑期多校训练营(第三场)A.Clam and Fish 题目链接 题目描述 There is a fishing game as following: The game contains ...

  10. 2020牛客暑期多校训练营(第五场)——E Bogo Sort

    2020牛客暑期多校训练营(第五场)--E Bogo Sort 题目描述 Today Tonnnny the monkey learned a new algorithm called Bogo So ...

最新文章

  1. 解决SVN 每次操作都需要重输入用户名密码问题
  2. 阿里巴巴在 Serverless 计算领域的探索
  3. 使用DOM解析常用方法
  4. c++ primer5th,习题12.24
  5. 计算机python技术基础知识点_python基础--相关计算机基础知识
  6. arduino智能浇花系统_arduino+水泵+继电器+RFID
  7. 《天天数学》连载29:一月二十九日
  8. 基于节点类的二叉树实现及部分操作函数
  9. 普通话转粤语_语音转文字评测:几款语音转文字app,你了解多少?
  10. 微信支付 支付成功后不跳转 ecshop微信支付 如下操作即可
  11. 设计模式_01单例模式
  12. Cisco无线AP在复杂企业环境配置指南
  13. 虚拟机克隆后没有IP
  14. 网站日志统计案例分析与实现
  15. 打印系统开发(56)——打印机驱动程序设计指南
  16. 欧洲机器人实验室盘点
  17. Windows Mobile下的重力感应器(Gravitational Sensor)开发
  18. windows 10环境下docker 部署RocketMq和RocketMq-Consol 控制台
  19. 阿里云王牌架构师杨曦:也谈系统缓存设计误区及高阶使用技巧
  20. 如何把mac照片导入u盘_macbook air里的相片要怎么放到u盘里?

热门文章

  1. VersaBank开发“数字保险箱”区块链服务
  2. ThreadPoolExecutor线程池 —————— 开开开山怪
  3. 瑞尔森大学的计算机科学专业,瑞尔森大学专业介绍
  4. steam在连接至steam服务器时发生错误解决办法
  5. Win10卸载 人脉
  6. 如何在VeryCD中下载资源
  7. 用matlab求二重积分
  8. python找出连续的最长的字母串
  9. 应用宝shangjia安全评估报告_你的APP上架,遇到【安全评估报告】这道门槛了吗?...
  10. uni-app设置页面背景及背景图片