Luogu P3600 随机数生成器

题目描述

sol研发了一个神奇的随机数系统,可以自动按照环境噪音生成真·随机数。

现在sol打算生成\(n\)个\([1,x]\)的整数\(a_1...a_n\),然后进行一些询问。

\(q\)次询问,每次询问i有两个参数\(li\)和\(ri\),sol会计算\(\min_{li \leq j \leq ri} a_j\)(a数组中下标在\(li、ri\)之间的数的最小值)。

最后测试结果会是这些询问得到的结果的最大值。

sol进行了很多次实验,现在他想问问你测试结果的期望大小是多少,对\(666623333\)取模。

输入输出格式

输入格式:

第一行三个数\(n、x、q\)。

下面q行,第i行两个数表示\(li\)和\(ri\)。

输出格式:

一行一个数,表示答案。

输入输出样例

输入样例#1:

2 2 1
1 2

输出样例#1:

499967501

输入样例#2:

6 6 6
1 3
2 4
3 5
4 6
5 6
3 4

输出样例#2:

88571635

根据整数期望公式:

\[\begin{align}
ans&=\sum_{i=1}^xi*p(X=i)\\
&=\sum_{i=1}^xp(X\geq i)\\
&=\sum_{i=1}^x1-p(X<i)
\end{align}
\]

因为是所有的最小值取最大值,所以\(p(X<i)\)比\(p(X\geq i)\)好求一些。

我们考虑对每个\(i\)分别求。

合法情况要求询问的每个区间中至少有一个\(<i\)的数。如果两个区间有包含关系,很明显大的区间没有用。将剩余的区间按左端点排序后,对于坐标上的每个点,包含它的区间的编号一定是连续的。所以我们将问题转换:有很多区间,选择一个区间的概率为\(P\),要选择一些区间将整个坐标轴覆盖,问概率。

很明显这些区间的左右端点都是单调不下降的(去掉无用区间)。设\(f_i\)表示最后一个选择的区间为\(i\),并且将\(r_i\)以及之前的坐标都覆盖了的概率。

\[f_i=\sum_{r_j\geq l_i-1}f_j*P*(1-P)^{i-j-1}
\]

前缀和优化一下单次\(DP\)就可以做到\(O(n)\)了。

代码:

#include<bits/stdc++.h>
#define ll long long
#define N 2005 using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;} const ll mod=666623333;
ll ksm(ll t,ll x) {
ll ans=1;
for(;x;x>>=1,t=t*t%mod)
if(x&1) ans=ans*t%mod;
return ans;
} int n,x,m;
struct interval {
int l,r;
bool operator <(const interval &a)const {
if(l!=a.l) return l<a.l;
return r>a.r;
}
}s[N]; interval st[N];
int top; int L[N],R[N];
ll ans;
ll DP(ll p) {
if(p==1) return 1;
static ll f[N],pw[N],inv[N];
memset(f,0,sizeof(f)); pw[0]=inv[0]=1;
for(int i=1;i<=n;i++) pw[i]=pw[i-1]*(mod+1-p)%mod;
inv[1]=ksm(mod+1-p,mod-2);
for(int i=2;i<=n;i++) inv[i]=inv[i-1]*inv[1]%mod;
f[0]=1;
int lx=0,rx=0;
ll sum=1;
for(int i=1;i<=n;i++) {
while(lx<=i&&R[lx]<L[i]-1) {
sum=(sum-f[lx]*inv[lx]%mod+mod)%mod;
lx++;
}
while(rx+1<i&&R[rx+1]>=L[i]-1) {
sum=(sum+f[rx+1]*inv[rx+1])%mod;
rx++;
}
f[i]=sum*p%mod*pw[i-1]%mod;
}
ll ans=0;
for(int i=1;i<=n;i++) {
if(R[i]==m) (ans+=f[i]*pw[n-i])%=mod;
}
return ans;
} int main() {
n=Get(),x=Get(),m=Get();
for(int i=1;i<=m;i++) s[i].l=Get(),s[i].r=Get();
sort(s+1,s+1+m);
for(int i=1;i<=m;i++) {
while(top>=1&&st[top].r>=s[i].r) top--;
st[++top]=s[i];
} m=top;
for(int i=1;i<=m;i++) s[i]=st[i]; for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) if(s[j].l<=i&&i<=s[j].r) R[i]=j;
for(int j=m;j>=1;j--) if(s[j].l<=i&&i<=s[j].r) L[i]=j;
}
top=0;
for(int i=1;i<=n;i++) {
if(L[i]&&R[i]) L[++top]=L[i],R[top]=R[i];
}
n=top;
ll invx=ksm(x,mod-2);
for(int i=1;i<=x;i++) {
(ans+=mod+1-DP((i-1)*invx%mod))%=mod;
}
cout<<ans;
return 0;
}

Luogu P3600 随机数生成器的更多相关文章

  1. Luogu P3600 随机数生成器(期望+dp)

    题意 有一个长度为 \(n\) 的整数列 \(a_1, a_2, \cdots, a_n\) ,每个元素在 \([1, x]\) 中的整数中均匀随机生成. 有 \(q\) 个询问,第 \(i\) 个询 ...

  2. luogu P3600 随机数生成器【dp】

    把期望改成方案数最后除一下,设h[i]为最大值恰好是i的方案数,那么要求的就是Σh[i]*i 首先包含其他区间的区间是没有意义的,用单调栈去掉 然后恰好不好求,就改成h[i]表示最大值最大是i的方案数 ...

  3. 洛谷P3600 随机数生成器(期望dp 组合数)

    题意 题目链接 Sol 一条重要的性质:如果某个区间覆盖了另一个区间,那么该区间是没有用的(不会对最大值做出贡献) 首先不难想到枚举最终的答案\(x\).这时我们需要计算的是最大值恰好为\(x\)的概 ...

  4. P3600 随机数生成器

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  5. 洛谷P3600随机数生成器——期望+DP

    原题链接 写到一半发现写不下去了... 所以orz xyz32768,您去看这篇题解吧,思路很清晰,我之前写的胡言乱语与之差距不啻天渊 #include <algorithm> #incl ...

  6. 洛谷 P3600 - 随机数生成器(期望 dp)

    题面传送门 我竟然独立搞出了这道黑题!incredible! u1s1 这题是我做题时间跨度最大的题之一-- 首先讲下我四个月前想出来的 \(n^2\log n\) 的做法吧. 记 \(f(a)=\m ...

  7. luogu P2354 [NOI2014]随机数生成器 贪心 卡空间 暴力

    LINK:随机数生成器 观察数据范围还是可以把矩阵给生成出来的. 考虑如何求出答案.题目要求把选出的数字从小到大排序后字典序尽可能的小 实际上这个类似于Mex的问题. 所以要从大到小选数字 考虑选择一 ...

  8. 【原创】开源Math.NET基础数学类库使用(13)C#实现其他随机数生成器

                   本博客所有文章分类的总目录:[总目录]本博客博文总目录-实时更新  开源Math.NET基础数学类库使用总目录:[目录]开源Math.NET基础数学类库使用总目录 前言 ...

  9. 【BZOJ-3122】随机数生成器 BSGS

    3122: [Sdoi2013]随机数生成器 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1362  Solved: 531[Submit][Sta ...

随机推荐

  1. 复杂的POI导出Excel表格(多行表头、合并单元格)

    poi导出excel有两种方式: 第一种:从无到有的创建整个excel,通过HSSFWorkbook,HSSFSheet HSSFCell, 等对象一步一步的创建出工作簿,sheet,和单元格,并添加 ...

  2. 数据库 tcp协程实现并发 回调函数

    数据库 tcp协程实现并发 回顾 一.回顾 进程池,线程池,回调函数 # from gevent import monkey;monkey.patch_all() #补丁 from gevent im ...

  3. Anaconda创建环境失败,提示无法定位程序输入点

    https://blog.csdn.net/qq_37465638/article/details/100071259 这篇博客写得很清楚,是anaconda下Library下lib下的一个文件和DD ...

  4. dp习题

    仅收录有意思的题目 数的划分 导弹拦截 : LIS的两种优化 教主的花园:将不同的情况分类,最后取max 午餐 & 挂饰: 需要排序 挂饰:0-1背包处理负数体积 投资的最大效益 : 完全背包 ...

  5. Bandizip解压压缩软件

    上次重装系统以后,特别注意安装软件,在这里提一些比较好的 解压软件:Bandizip 这个是一个免费轻量级的软件,压缩解压速度快,没什么广告,推荐大家在官方下载 Bandizip下载网址 点击下载安装 ...

  6. Redis的List的删除

    Redis的List命令里没有根据index删除元素的命令,但有的时候业务会需要这个功能. 先上命令: LSET ListKey index "__deleted__"LREM L ...

  7. 【STM32-V7】STM32H743XIH6开发板,丰富软件资源,强劲硬件配置,大量软件解决方案持续更新中(2019-12-12)

    说明: 争取做更多的实战性应用,分享更多的嵌入式技术,希望能在实际项目中帮到大家. (1)V7将大力加强对初学者的支持力度,已经更新至63章,下载链接,后37章和一批视频教程将加紧制作. (2)事隔五 ...

  8. 禧云Redis跨机房双向同步实践

    编者荐语: 2019年4月16日跨机房Redis同步中间件(Rotter)上线,团餐率先商用: 以下文章来源于云纵达摩院 ,作者杨海波   禧云信息/研发中心/杨海波 20191115 关键词:Rot ...

  9. Microsemi Libero系列教程(一)——Libero开发环境介绍、下载、安装与注册

    前言 相比与Xilinx和Altera在国内的市场,Microsemi的FPGA在国内应用很少很少,网上几乎没有详细的教程,刚开始使用时,遇到了各种问题,自己也走了不少弯路.本系列教程以Libero ...

  10. Cypress 之 URL访问

    visit 作用: 访问一个远程URL. (建议:使用前设置 baseUrl) 语法: cy.visit(url) cy.visit(url, options) cy.visit(options) 使 ...